Generated: Tue Jun 8 17:26:27 2010 from amsrcs02.pl 2010/04/14 97.1 KB.
# ########################################################################################### # NAME: amsrcs02.pl # AIM: MAKE DSP FILES - Given a folder, trace the makefile.am files, collecting # libraries, applications and sources # Show 'projects' found, and SHOW the sources of each. # AND write a DSP file for each!!! # While it confidently outputs a set of DSP files, and a DSW file, in # complex cases these will not work very well, as it MISSES lots of includes, and libraries # ================================ # 10/02/2010 - Review of this script # ONLY GENERATES TEMPORARY DSP FILE(S), and 'temp_list.dsw' if the option $write_temp_ds is set to 1 # Add DSP 'sources' relative to a $target_dir, Remove a warning about no GROUP # # 2009-06-09 - change error exit to WARNING only, and continue processing # 2009-05-09 - Add or ensure _CRT_SECURE_NO_DEPRECATE is added to defines # 22/11/2008 - Problem, perhaps, in that it 'splits' fgfs into MANY libraries # which is perhpas how it should be??? # Also see am2dsp[n].pl as well, which is the opposite, in that is COMBINES # everything, including 'test' and 'utilties' into ONE ... and puts ALL the objects # into Debug or Release, which would NOT account for duplicates! # Also scan the 'top' directory for ALL FILE, # and show files NOT in a project # Add projects NOT addressed by main configure.ac and makefile.am # 17/11/2007 - geoff mclane - http://geoffair.net/mperl # # The process # # Read the configure.ac file, and build a set of contents # and put inputs into @make_input_list, or @other_input_files # which are then put in @input_files ... set $dgb20 to see list as processed # # Each @input_files, and later @other_inputs (makefile.am) is processed in process_am_file() # Sources are added to @msvc_c_files in form 'Lib/Project | Source | Title' # extract_am_project then separates these into $am_projects{$lib} .= ['|'.]$lsc; # # The %am_project's are shown by show_am_projects( $main_root_dir ); # Then the 'other' projects are shown - show_other_projects( $main_root_dir ); # and finally all source files found show_all_sources( "makefile.am set", $main_root_dir ); # 04/04/2008 - add read of sub-directory 'configure.ac' if present ... # 22/11/2008 - add /GR to DSP, and removed all \r output # ########################################################################################### use strict; use warnings; use File::Basename; # to split path into ($name, $dir) = fileparse($ff); or ($nm,$dir,$ext) = fileparse( $fil, qr/\.[^.]*/ ); require 'logfile.pl' or die "Unable to load logfile.pl ...\n"; require 'relative.pl' or die "Unable to load relative.pl ...\n"; require 'chkmain.pl' or die "Unable to load chkmain.pl ...\n"; require 'utils.pl' or die "Unable to load utils.pl ...\n"; # log file stuff my ($LF); my $pgmname = $0; if ($pgmname =~ /\w{1}:\\.*/) { my @tmpsp = split(/\\/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = "temp.$pgmname.txt"; my $pack = $pgmname; open_log($outfile); prt( "$0 ... Hello, World ...\n" ); my $main_root_dir = "C:\\FG\\32\\Atlas\\"; #my $main_root_dir = "C:\\FGCVS\\SimGear\\source\\"; my $target_dir = $main_root_dir."projects\\msvc"; #my $main_root_dir = "C:\\FG\\SimGear\\"; #my $main_root_dir = "C:\\FGCVS\\SimGear\\source\\"; #my $target_dir = $main_root_dir."projects\\msvc"; # features my $load_log = 0; # load logfile into notepad at end my $write_temp_ds = 1; my $add_CRT_SECURE_NO_DEPRECATE = 1; my $add_NOMINMAX = 1; #my $add_SOURCE_REL = 0; #my $src_relative = "..\\.."; my $add_CONFIG_H = 1; my $recheck_am = 0; # a debug RE-CHECK of makefile.am files for a reference my $check_full = 1; # check for the FULL file name my $long_line = " C:\\FGCVS\\FlightGear\\source\\scripts\\example\\fgfsclient.cxx "; my $min_line = length($long_line); my $check4main = 1; # check if the NOT FOUND modules have a main() service my $check4main2 = 1; # check if the source has a main() service my $show_main = 0; # actually SHOW the main my $show_cond = 0; # actually SHOW the condition for main my $one_line = 0; # output sources in ONE line my $add_rel_src = 1; # add the relative source to output ############################### ####### ONLY DSP STUFF ######## my $out_dsp = 1; # output a MAIN DSP and DSW files my $out_dsp2 = 1; # output a secondary DSP files ################################################# my $msvc_cflags = ''; # see %am_includes and %am_cppflags # hash by project, the CPPFLAGS, if ANY my $msvc_libs = ''; # see %am_libadds = (); # hash by project, the LDADD, if ANY my $msvc_dlibs = ''; my $msvc_rlibs = ''; my $last_project = ''; my $last_dsp_file = ''; my @dspinfo = (); ############################ ###################### # constants my $IGNORE_PATTERN = "^##([^#].*)?\$"; my $WHITE_PATTERN = "^[ \t]*\$"; my $COMMENT_PATTERN = "^#"; my $RULE_PATTERN = "^([\$a-zA-Z_.][-.a-zA-Z0-9_(){}/\$]*) *:([^=].*|)\$"; my $SUFFIX_RULE_PATTERN = "^\\.([a-zA-Z]+)\\.([a-zA-Z]+)\$"; # like say bin_PROGRAMS = abc xyz my $MACRO_PATTERN = "^([A-Za-z][A-Za-z0-9_]*)[ \t]*([:+]?)=[ \t]*(.*)\$"; my $BOGUS_MACRO_PATTERN = "^([^ \t]*)[ \t]*([:+]?)=[ \t]*(.*)\$"; my $IF_PATTERN = "^if[ \t]+\([A-Za-z][A-Za-z0-9_]*\)[ \t]*\(#.*\)?\$"; my $ELSE_PATTERN = "^else[ \t]*\(#.*\)?\$"; my $ENDIF_PATTERN = "^endif[ \t]*\(#.*\)?\$"; my $PATH_PATTERN='(\\w|/|\\.)+'; # This will pass through anything not of the prescribed form. my $INCLUDE_PATTERN = "^include[ \t]+((\\\$\\\(top_srcdir\\\)/${PATH_PATTERN})|(\\\$\\\(srcdir\\\)/${PATH_PATTERN})|([^/\\\$]${PATH_PATTERN}))[ \t]*(#.*)?\$"; my $AM_CONDITIONAL_PATTERN = "AM_CONDITIONAL\\((\\w+)"; my $AM_INIT_AUTOMAKE = "AM_INIT_AUTOMAKE\\(([^,]+),[ \t]*([^)]+)"; #### type constants my $TYPE_NONE = 0; my $TYPE_C = 1; my $TYPE_H = 2; my $TYPE_DSW = 3; my $TYPE_SLN = 4; my $TYPE_AM = 5; my $TYPE_MAK = 6; ###################### # program variables my $exit_status = 0; my @input_files = (); my @make_input_list = (); my @other_input_files = (); my %output_files = (); my %make_list = (); my %am_vars = (); my %def_type = (); my @excluded_dirs = (); my @var_list = (); my $dsp_package = ''; my $dsp_version = ''; my %configure_cond = (); my %configure_vars = (); my %cfg_defines = (); my @config_fullnames = (); my @config_names = (); my @config_headers = (); my $config_header_line = ''; ####my $am_file = ''; my @msvc_c_extra = (); my @msvc_h_extra = (); my @msvc_o_extra = (); my @done_am = (); # list of AM files read my @warnings = (); my @ac_scanned = (); my %config_ac_macros = (); my %inc_hash = (); # These two variables are used when generating each Makefile.in. # They hold the Makefile.in until it is ready to be printed. my $output_vars = ''; my $output_trailer = ''; # This holds the contents of a Makefile.am, as parsed by # read_am_file. my %contents = (); # This holds the names which are targets. These also appear in # %contents. my %targets = (); # For a variable or target which is defined conditionally, this # holds an array of the conditional values. The array is composed # of pairs of condition strings (the variables which configure # will substitute) and values (the value of a target is # meaningless). For an unconditional variable, this is empty. my %conditional = (); # This holds the line numbers at which various elements of # %contents are defined. my %content_lines = (); # This holds a 1 if a particular variable was examined. my %content_seen = (); # This is the conditional stack. my @conditional_stack = (); # This holds the set of included files. my @include_stack = (); # This holds the "relative directory" of the current Makefile.in. # Eg for src/Makefile.in, this is "src". my $relative_dir = ''; # This maps the source extension of a suffix rule to its # corresponding output extension. my %suffix_rules = (); # per AM file sources my @am_c_files = (); my @am_h_files = (); my @am_o_files = (); ################# ### final source lists my @msvc_c_files = (); my @msvc_titles = (); my @msvc_h_files = (); my @msvc_o_files = (); my %other_projs = (); # store C/C++ sources under project names my %other_deps = (); # and store LIBRARY dependencies ..._LDADD, under project names my %am_projects = (); # store C/C++ sources under project names my %am_headers = (); # store H sources under project names my %am_includes = (); # hash by project, the INCLUDES, if ANY my %am_cppflags = (); # hash by project, the CPPFLAGS, if ANY my %am_libadds = (); # hash by project, the LDADD, if ANY my @all_files = (); my $active_am_file = ''; my $current_am_file = ''; my $next_am_file = ''; my ($fil_name, $fil_dir, $full_fil_path); my @dspprojs = (); # list of PROJECTS created ####################### # debug my $dbg1 = 0; # show EACH configure.ac line my $dbg2 = 0; # show "Storing configure_cond key $1 ... value=? ..." my $dbg2a = 0; # show if (/$AM_CONDITIONAL_PATTERN/o) { prt( "$aclnnum: [$acline]\n" ) if ($dbg2a); my $dbg3 = 0; # show "Substute $key=$nval ... setting $var_hash{$key} = $nval; my $dbg3a = 0; # show "MACRO [$key]=[$nval] my $dbg4 = 0; # show "Got ac_output_line = [$ac_output_line] ... my $dbg5 = 0; # show "Adding $input [$ff] to make_input_list ... my $dbg6 = 0; # list Makefile list found my $dbg7 = 0; # show each 'makefile' processed ... my $dbg8g = 1; # show "Group set to [$group] ... my $dbg8 = 0; # show "Group set to [$group] ... *AND* "Expanding variable $varname ... my $dbg9 = 0; # show "Added [$file] to C EXTRA list... my $dbg10 = 0; # show each makefile.am line ... my $dbg11 = 0; # show "NO contents for [$last_var_name]! ... my $dbg12 = 0; # show "End $last_var_name = ["... if !$saw_bk my $dbg13 = 0; # show "Found if $1, and condition is TRUE (see cfg_defines) ... my $dbg14 = 0; # show "Found a macro definition. 1[$1] 2[$2] 3[$3] ... something=something in Makefile.am my $dbg15 = 0; # show macro "NB: [$last_var_name] = [$contents{$last_var_name}]" . ... my $dbg16 = 1; # show "$pack: reading $am_file ... my $dbg17 = 0; # show "Sources ending in .$source_suffix become .$object_suffix ... my $dbg18 = 0; # show "Add $src to C list my $dbg19 = 0; # show %contents after makefile.am parse my $dbg20 = 1; # show "\nProcessing [$am_file] from input_files array ... my $dbg21 = 1; # show "Project: [$proj] - sources [$srcs] ... my $dbg22 = 1; # show CHECK ME always ... my $dbg23 = 0; # show directory content count - "Found ".scalar @dir_cont." items in [$fil] my $dbg24 = 0; # show "Processing AM file [" . $makefile . ".am] my $dbg25 = 0; # show "Got INCLUDES [$incs] ... my $dbg26 = 1; # show "For $group, saved INCLUDES [$incs] my $dbg27 = 0; # show checking for substitution macros ... my $dbg28 = 1; # show ALL %contents ... see $dbg19 also above to show more ... # that is show like "CT: Got $cnt items in \%contents ... file $file_am ... my $dbg29 = 0; # prt("[dbg_29] Found dependencies [$uproj]=[$srcs].\n") if ($dbg29); my $dbg30 = 0; # prt( "[dbg30] Ending last DSP - [$fil] ...\n" ) if ($dbg30); my $dbg_comm = 0; # show sifting of comments out of file lines my $dbg_incs = 0; # show sifting of 'include' out of file lines # Normally it was intended to read an am2cfg.def file, but set some anyway $cfg_defines{"HAVE_GLUT"} = 1; $cfg_defines{"HAVE_THREADS"} = 1; # forward references sub get_top_files($); sub fix_rel($); # FUNCTIONS # ===================================================== # general sub prtw($) { my ($wm) = shift; prt($wm); $wm =~ s/\n$//; push(@warnings,$wm); } sub prtd($) { my ($tx) = shift; prt($tx); $tx =~ s/\n$//; push(@dspinfo, $tx); } sub pgm_exit($$) { my ($val,$msg) = @_; if (@warnings) { prt( "\nREPEAT OF ".scalar @warnings." WARNINGS ...\n" ); foreach my $mg (@warnings) { prt("$mg\n"); } prt("\n"); } else { prt("No WARNINGS issued...\n"); } if (length($msg)) { $msg .= "\n" if (! ($msg =~ /\n$/) ); prt($msg); } close_log($outfile,$load_log); exit($val); } sub subract_target_dir($) { my ($fil) = shift; my $td = $target_dir; my $len = length($fil); if ($len > length($td)) { $len = length($td); my ($i); for ($i = 0; $i < $len; $i++) { last if (substr($td,$i,1) ne substr($fil,$i,1)); } $fil = substr($fil,$i); $fil =~ s/^(\\|\/)//; } return $fil; } sub has_no_extent($) { my ($fil) = shift; my ($fnm, $fdir, $fe) = fileparse( $fil, qr/\.[^.]*/ ); if (length($fe) == 0) { return 1; } return 0; } # specific sub exclude_cvs_svn($) { my ($dir) = shift; $dir = lc($dir); return 1 if ($dir eq '.svn'); return 1 if ($dir eq 'cvs'); return 0; } sub exclude_dir($) { my ($dir) = shift; foreach my $d (@excluded_dirs) { if ($dir =~ "/$d/") { return 1; } } return 0; } sub get_top_files($) { my ($td) = shift; my @dirs = (); my ($ff); $td = unix_2_dos($td); # ensure DOS form #$td .= "\\" if (substr($td,length($td)-1) ne "\\"); # add trailing, if none $td .= "\\" if !($td =~ /\\$/); # add trailing, if none if (opendir(DIR, $td)) { my @dfiles = readdir(DIR); close DIR; foreach my $df (@dfiles) { next if (($df eq '.') || ($df eq '..')); $ff = $td.$df; if (-f $ff) { my $typ = is_my_type($df); my ($nm,$dir) = fileparse($ff); #my $rd = get_relative_path( $dir, $td ); my $rd = get_relative_path_2( $dir, $td ); ##my $rd = unix_2_dos($rp); push(@all_files, [$df, $ff, 0, $typ, $rd]) if ($typ); } elsif (-d $ff) { push(@dirs,$ff) if (!exclude_cvs_svn($df)); } else { prtw( "WARNING: What is THIS [$ff] ???\n" ); } } } else { prtw( "WARNING: Unable to OPEN directory $td ...\n" ); } foreach $ff (@dirs) { get_top_files($ff); } } # fix relative directory - fix relative path - path fix # Remove any DOT or DOUBLE DOT from the PATH sub fix_rel($) { my ($path) = shift; $path = unix_2_dos($path); # ensure DOS separator my @a = split(/\\/, $path); # split on DOS separator my $npath = ''; my $wmsg = ''; my $max = scalar @a; my @na = (); for (my $i = 0; $i < $max; $i++) { my $p = $a[$i]; if ($p eq '.') { # ignore this } elsif ($p eq '..') { if (@na) { pop @na; # discard previous } else { prtw( "WARNING: Got relative .. without previous!!! [$path]" ); } } else { push(@na,$p); } } foreach my $pt (@na) { $npath .= "\\" if length($npath); $npath .= $pt; } return $npath; } sub is_c_source_ext($) { my ($ext) = shift; my $fe = lc($ext); if (($fe eq '.c')||($fe eq '.cxx')||($fe eq '.cpp')) { return 1; } return 0; } sub is_h_source_ext($) { my ($ext) = shift; my $fe = lc($ext); if (($fe eq '.h')||($fe eq '.hxx')||($fe eq '.hpp')) { return 1; } return 0; } sub is_am_source_ext($) { my ($ext) = shift; $ext = lc($ext); if ($ext eq '.am') { return 1; } return 0; } sub is_am_file($) { my ($fil) = shift; my ($fnm, $fdir, $fe) = fileparse( $fil, qr/\.[^.]*/ ); return is_am_source_ext($fe); } sub process_one_file($) { my $afile = shift; ($fil_name, $fil_dir) = fileparse($afile); #$full_fil_path = unix_2_dos($main_root_dir . $fil_dir); $full_fil_path = fix_rel($main_root_dir . $fil_dir); # also returns DOS, minus trailing '\' $full_fil_path .= "\\" if ( !($full_fil_path =~ /\\$/) ); # add trailing '\' IF $next_am_file = $afile; $next_am_file .= ".am" if (has_no_extent($afile) && !is_am_file($afile)); prt( "\nProcessing [$next_am_file] from input_files array ...\n" ) if ($dbg20); process_am_file($dsp_package, $afile, $main_root_dir) if !exclude_dir($afile); my $mk = mark_all_files(unix_2_dos($main_root_dir . $afile . '.am')); prtw( "WARNING: NOT FOUND IN MARK [".unix_2_dos($main_root_dir.$afile.".am")."]!\n" ) if (!$mk); } sub lib_in_projects($$) { my ($lib,$rp) = @_; foreach my $p (@{$rp}) { my ($dsp,$name) = split ',', $p; if ($lib eq $name) { return 1; } } return 0; } # 10/02/2010 Add dependencies # Package=<4> #{{{ # Begin Project Dependency # Project_Dep_Name SimGear # End Project Dependency #}}} sub generate_dsw($$$) { my ($dsw_name, $rpacks, $rdeps) = @_; my ($proj,@arr,$lib,$deps,$lib2); prtd( "Creating $dsw_name ...\nrenaming any original to OLD or BAK ...\n" ); rename_2_old_bak( $dsw_name ); open(DSW, ">$dsw_name") || mydie( "Can't create $dsw_name: $!\n" ); print DSW <<EOF; Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! EOF foreach my $p (@{$rpacks}) { print DSW "###############################################################################\n\n"; my ($dsp,$name) = split ',', $p; print DSW "Project: \"$name\"=\"$dsp\" - Package Owner=<4>\n\n"; print DSW <<EOF; Package=<5> {{{ }}} EOF print DSW "Package=<4>\n"; print DSW "{{{\n"; foreach $proj (keys %{$rdeps}) { if ($proj eq $name) { $deps = ${$rdeps}{$proj}; @arr = split(/\*/,$deps); if (@arr) { foreach $lib (@arr) { $lib2 = "lib".$lib; if (lib_in_projects($lib2,$rpacks)) { print DSW " Begin Project Dependency\n"; print DSW " Project_Dep_Name $lib2\n"; print DSW " End Project Dependency\n"; } else { prtw("WARNING: [$lib2] NO FOUND in PROJECTS!\n"); } } } last; } } print DSW "}}}\n\n"; } print DSW <<EOF; ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### EOF close(DSW); prtd("Written $dsw_name...\n"); } sub gen_temp_dsw($) { my ($rd) = shift; # = $main_root_dir $rd =~ s/(\\|\/)$//; # s/\\$//; my $out_file = 'temp_list.dsw'; # ONLY generate a TEMP DSW ########################## if ($write_temp_ds) { if (length($dsp_package)) { $out_file = 'temp.'.$dsp_package.'.dsw'; } else { $out_file = 'temp_list.dsw'; } } else { $out_file = $target_dir; $out_file .= "\\" if !($out_file =~ /(\\|\/)$/); if (length($dsp_package)) { $out_file .= $dsp_package; } else { my ($f,$d) = fileparse($rd); $out_file .= $f; } $out_file .= '.dsw'; } #$out_file = $outdir.$in_file.'.dsw'; # DSW file, @packs generate_dsw( $out_file, \@dspprojs, \%other_deps ); } # ===================================================== prt( "Moment, getting full file list of $main_root_dir ...\n" ); get_top_files( $main_root_dir ); prt( "Got ".scalar @all_files." files ...\n" ); scan_root_folder( $main_root_dir ); if (@input_files) { my @inf = @input_files; prt( "Processing ".scalar @inf." files...\n" ); foreach my $fil (@inf) { process_one_file($fil); } } my @other_inputs = get_missed_makes($main_root_dir); if (@other_inputs) { prt( "Other AM files, not used = ".scalar @other_inputs." ...\n" ); foreach my $afile (@other_inputs) { ($fil_name, $fil_dir) = fileparse($afile); ##$full_fil_path = unix_2_dos($main_root_dir . $fil_dir); $full_fil_path = fix_rel($main_root_dir . $fil_dir); # also returns DOS, minus trailing '\' $full_fil_path .= "\\" if ( !($full_fil_path =~ /\\$/) ); # add trailing '\' IF $next_am_file = $afile; $next_am_file .= ".am" if (has_no_extent($afile) && !is_am_file($afile)); prt( "\nProcessing other [$next_am_file] in ($full_fil_path) ...\n" ); process_am_file('Others', $afile, $main_root_dir) if !exclude_dir($afile); my $mk = mark_all_files(unix_2_dos($main_root_dir . $afile )); prtw( "WARNING: NOT FOUND IN MARK [".unix_2_dos($main_root_dir.$afile)."]!\n" ) if (!$mk); } } my $c_cnt = scalar @msvc_c_files; my $t_cnt = scalar @msvc_titles; my $h_cnt = scalar @msvc_h_files; my $o_cnt = scalar keys(%other_projs); prt( "c_cnt = $c_cnt, h_cnt = $h_cnt, t_cnt = $t_cnt, o_cnt = $o_cnt ...\n" ); extract_am_projects(); my $p_cnt = scalar keys(%am_projects); prt( "Moment, generating inc_hash ... from $p_cnt AM projects ...\n" ); gen_inc_hash_am( $main_root_dir ); gen_inc_hash_others( $main_root_dir ); ### show_inc_hash(); prt( "Done generating inc_hash ...\n" ); show_am_projects( $main_root_dir ); show_other_projects( $main_root_dir ); show_all_sources( "makefile.am set", $main_root_dir ); gen_temp_dsw( $main_root_dir ); if (@dspinfo) { prt( "\nRepeat show of ".scalar @dspinfo." lines of DSP info ...\n" ); foreach my $di (@dspinfo) { prt("$di\n"); } } pgm_exit($exit_status,""); ####################################################################### ##### all subs below sub extract_am_projects { my ($file, @arr, $lib, $lsc); foreach $file (@msvc_c_files) { ##prt( "$file\n" ); @arr = split(/\|/ , $file); # get Lib | Source | Title if (scalar @arr == 3) { $lib = $arr[0]; $lsc = $arr[1]; if (defined $am_projects{$lib}) { $am_projects{$lib} .= '|'.$lsc; } else { $am_projects{$lib} = $lsc; } } else { prtw( "WARNING: Did NOT split as EXPECTED!!! [$file] ...\n\n" ); } } # 2009-06-09 - also extract the HEADERS foreach $file (@msvc_h_files) { ##prt( "$file\n" ); @arr = split(/\|/ , $file); # get Lib | Source | Title if (scalar @arr == 3) { $lib = $arr[0]; $lsc = $arr[1]; if (defined $am_headers{$lib}) { $am_headers{$lib} .= '|'.$lsc; } else { $am_headers{$lib} = $lsc; } } else { prtw( "WARNING: Did NOT split as EXPECTED!!! [$file] ...\n\n" ); } } } sub gen_inc_hash_others { my ($rd) = shift; my ($lsrcs, @arr, $s, $ind, $ff, $mk, $om); my ($in_file, $in_dir, $rel_src); my $out_file = ''; my @incs = (); $last_dsp_file = ''; foreach my $key (keys %other_projs) { $lsrcs = $other_projs{$key}; # extract LIST of SOURCES @arr = split(/\*/, $lsrcs); # get sources foreach $s (@arr) { $ind = index($s, '$(top_srcdir)'); $s = substr($s, $ind + 14) if ($ind >= 0); $s = fix_rel($s); $ff = $rd . $s; @incs = (); get_include_list($ff, \@incs); if (defined $inc_hash{$s}) { prtw( "WARNING: [$s] ALREADY IN inc_hash!\n" ); $inc_hash{$s} .= join(' ', @incs); } else { $inc_hash{$s} = join(' ', @incs); } } } } sub gen_inc_hash_am { my ($rd) = shift; my ($s, $ff, $mk, $om); my ($lsrcs, @arr); my @incs = (); foreach my $key (keys %am_projects) { $lsrcs = $am_projects{$key}; @arr = split(/\|/ , $lsrcs); # Sources foreach $s (@arr) { $s = fix_rel($s); $ff = $rd . $s; @incs = (); get_include_list($ff, \@incs); if (defined $inc_hash{$s}) { prtw( "WARNING: [$s] ALREADY IN inc_hash!\n" ); $inc_hash{$s} .= join(' ',@incs); } else { $inc_hash{$s} = join(' ',@incs); } } } } sub show_other_projects { my ($rd) = shift; my ($lsrcs, @arr, $s, $ind, $ff, $mk, $om); my ($in_file, $in_dir, $rel_src); my $out_file = ''; $last_dsp_file = ''; prt( "\nFound $o_cnt OTHER projects ...root = $rd\n" ); foreach my $key (keys %other_projs) { $lsrcs = $other_projs{$key}; # ONLY GENERATE TEMPORARY DSP FILE if ($write_temp_ds) { $out_file = 'temp.'.$key.'.dsp'; } else { $out_file = $target_dir; $out_file .= "\\" if !($out_file =~ /(\\|\/)$/); $out_file .= $key.'.dsp'; } push(@dspprojs, ".\\$key.dsp,$key"); @arr = split(/\*/, $lsrcs); # get sources SPLIT if ($one_line) { $lsrcs =~ s/\*/, /g; prt( "Project: $key = $lsrcs\n" ); } else { prt( "Project: $key\n" ); } foreach $s (@arr) { $ind = index($s, '$(top_srcdir)'); $s = substr($s, $ind + 14) if ($ind >= 0); $s = fix_rel($s); $ff = $rd . $s; $mk = mark_all_files($ff); ($in_file, $in_dir) = fileparse($ff); # source, target #$rel_src = get_relative_path( $in_dir, $outdir ); #$rel_src = get_relative_path_2( $in_dir, $outdir ); $rel_src = get_relative_path_2( $in_dir, $target_dir ); $rel_src .= $in_file; $rel_src = unix_2_dos($rel_src); if (is_c_source($s)) { if ($check4main2) { $om = get_main_msg($ff,$s,0,$rel_src); # check if a main() } else { $om = "C $s "; $om .= "(rs=$rel_src)" if ($add_rel_src); } $om .= "NOT FOUND IN MARK!" if (!$mk); prt("$om\n"); if ($out_dsp2) { # generate DSP file out_dsp_file($key, $out_file, $rel_src, $rd, 0); } } else { $om = "H $s "; $om .= "(rs=$rel_src)" if ($add_rel_src); $om .= "NOT FOUND IN MARK!" if (!$mk); prt("$om\n"); } } } if ( length($last_dsp_file) ) { end_dsp_file($last_dsp_file); } } # need 'root' to do DSP/DSW sub show_am_projects { my ($rd) = shift; prt( "\nFound $p_cnt LIBRARY projects ...root = $rd\n" ); my $out_file = ''; my ($in_file, $in_dir, $rel_src); my ($s, $ff, $mk, $om); my ($lsrcs, @arr); foreach my $key (keys %am_projects) { $lsrcs = $am_projects{$key}; # ONLY GENERATE A TEMPORARY DSP FILE #$out_file = $outdir.$key.'.dsp'; #$out_file = 'temp.'.$key.'.dsp'; if ($write_temp_ds) { $out_file = 'temp.'.$key.'.dsp'; } else { $out_file = $target_dir; $out_file .= "\\" if !($out_file =~ /(\\|\/)$/); $out_file .= $key.'.dsp'; } # and store the relative actual DSP file name, for DSW generation push(@dspprojs, ".\\$key.dsp,$key"); @arr = split(/\|/ , $lsrcs); # Sources if ($one_line) { foreach $s (@arr) { $ff = fix_rel($rd . $s); $mk = mark_all_files($ff); if ($out_dsp) { ($in_file, $in_dir) = fileparse($ff); # source, target #$rel_src = get_relative_path( $in_dir, $outdir ); #$rel_src = get_relative_path_2( $in_dir, $outdir ); $rel_src = get_relative_path_2( $in_dir, $target_dir ); $rel_src .= $in_file; $rel_src = unix_2_dos($rel_src); # generate TEMP DSP file out_dsp_file($key, $out_file, $rel_src, $rd, 1); } } $lsrcs =~ s/\|/, /g; prt( "Project: $key = $lsrcs\n" ); } else { prt( "Project: $key\n" ); foreach $s (@arr) { $s = fix_rel($s); $ff = $rd . $s; ($in_file, $in_dir) = fileparse($ff); # source, target #$rel_src = get_relative_path( $in_dir, $outdir ); #$rel_src = get_relative_path_2( $in_dir, $outdir ); $rel_src = get_relative_path_2( $in_dir, $target_dir ); $rel_src .= $in_file; $rel_src = unix_2_dos($rel_src); $mk = mark_all_files($ff); if ($check4main2) { $om = get_main_msg($ff,$s,0,$rel_src); # check if a main() } else { $om = " $s "; $om .= "(rs=$rel_src)" if ($add_rel_src); } if (!$mk) { $om .= " NOT FOUND in MARK!"; } prt("$om\n"); if ($out_dsp) { # genarate TEMP DSP file out_dsp_file($key, $out_file, $rel_src, $rd, 1); } } } } if ( length($last_dsp_file) ) { end_dsp_file($last_dsp_file); $last_dsp_file = ''; $last_project = ''; } } sub get_main_msg { my ($ffn,$sfn,$no,$rs) = @_; my $fom = " $sfn "; $fom .= "(rs=$rs)" if ($add_rel_src); my @cm = (); if (chk_main($ffn,\@cm)) { while (length($fom) < $min_line) { $fom .= ' '; } $fom .= "HAS main()"; my $cmc = scalar @cm; for (my $t = 0; $t < $cmc; $t++) { $fom .= "\n ".$cm[$t][0].": ".$cm[$t][1] if ($show_main); if (length($cm[$t][2])) { if ($show_cond) { $fom .= " cond ".$cm[$t][2]; } else { $fom .= " cond"; last; } } } } elsif ($no) { while (length($fom) < $min_line) { $fom .= ' '; } $fom .= "NO main() FOUND"; } return $fom; } sub scan_root_folder { my ($rd) = shift; $rd .= "\\" if !(substr($rd,-1,1) =~ /(\\|\/)/); my $ff = $rd; $ff .= 'configure.ac'; prt( "Scanning [$ff] file ...\n" ); scan_one_configure_file($ff,$rd); $ff = $rd.'aclocal.m4'; scan_one_configure_file($ff,$rd) if -f $ff; if (!@input_files) { prt( "Copying " . scalar @make_input_list . " make_input_list to input_files.\n" ); @input_files = @make_input_list; %output_files = %make_list; } else { prt( "input_files has list of " . scalar @input_files . " ...\n" ); } if ($dbg6) { my $cnt = scalar @input_files; prt( "\nOutput of $cnt input_files list ...\n" ); $cnt = 0; foreach $ff (@input_files) { $cnt++; prt( "$cnt $ff\n" ); } prt( "Done $cnt input_files list ...\n" ); } } sub is_in_ac_done { my ($fil) = shift; foreach my $sd (@ac_scanned) { if( uc($fil) eq uc($sd) ) { return 1; } } return 0; } ## my %config_ac_macros = (); sub do_macro_sub2 { my ($item) = shift; prt( "Checking substitution for [$item] ...\n" ) if ($dbg27); if (defined $config_ac_macros{$item}) { # if it is IN the MACROS my $ritem = $config_ac_macros{$item}; # extract the substitute value prt( "Found: returning [$ritem] ...\n" ) if ($dbg27); return $ritem; } return $item; } sub do_macro_sub { my ($item) = shift; if ($item =~ /^\$/) { my $msub = substr($item,1); # remove leading '$' my $ritem = do_macro_sub2($msub); if ($ritem ne $msub) { return $ritem; } } return $item; } sub scan_one_configure_file { my ($filename, $rd) = @_; if( is_in_ac_done($filename) ) { return; } if (! open(CONFIGURE, $filename) ) { prtw( "WARNING: can't open '$filename': $!\n" ); return; } push(@ac_scanned, $filename); prt( "Processing configure file - $filename ...\n" ); my $in_ac_output = 0; my $ac_output_line = ''; my $ff = ''; my $fline = ''; my $cline = ''; my $acline = ''; my $aclnum = 0; my %var_hash = (); my $key = ''; my $nval = ''; while (<CONFIGURE>) { $fline = $_; # get current file line $cline = $fline; # copy current file line chomp $cline; $acline = trim_all($cline); $aclnum++; ###prt( "$cline\n" ); # Remove comments from current line. s/\bdnl\b.*$//; s/\#.*$//; $cline =~ s/\bdnl\b.*$//; $cline =~ s/\#.*$//; next if (length($cline) == 0); prt( "$cline\n" ) if ($dbg1); if ($cline =~ /^(\w+)="(\d+)"$/) { prt( "Num Variable $1=$2\n" ) if ($dbg3); $var_hash{$1} = $2; ##} elsif ($cline =~ /^(\w+)="(.+)"$/) { ##} elsif ($cline =~ /^(\w+)="{0,1}(.+)"{0,1}$/) { ##} elsif ($cline =~ /^(\w+)=(.+)$/) { } elsif ($cline =~ /^\s*(\w+)=(.+)$/) { $key = $1; $nval = $2; if (substr($nval,0,1) eq '"') { $nval = substr($nval,1, length($nval)-2); } prt( "MACRO [$key]=[$nval]\n" ) if ($dbg3a); if (index($nval,'.') != -1) { my @varr = split(/\./,$nval); $nval = ''; my $vlen = scalar @varr; prt( "Split to $vlen components ...\n" ) if ($dbg3); for (my $i = 0; $i < $vlen; $i++) { my $ky = trim_line($varr[$i]); prt( "Conponent $ky\n" ) if ($dbg3); if (substr($ky,0,1) eq '$') { $ky = substr($ky,1); if (defined $var_hash{$ky}) { $nval .= '.' if (length($nval)); $nval .= $var_hash{$ky}; } else { $nval .= '.' if (length($nval)); $nval .= $ky; } } else { $nval .= '.' if (length($nval)); $nval .= $ky; } } } prt( "Available substitute [$key]=[$nval]\n" ) if ($dbg3); $var_hash{$key} = $nval; $config_ac_macros{$key} = $nval; } elsif ($cline =~ /^(\w+)=(.+)$/) { $key = $1; $nval = $2; prtw( "WARNING: This should have already been processed!\nWARNING: Variable [$key]=[$nval] no quotes\n\n" ); } # Skip macro definitions. Otherwise we might be confused into # thinking that a macro that was only defined was actually # used. next if /AC_DEFUN/; # Follow includes. This is a weirdness commonly in use at # Cygnus and hopefully nowhere else. if (/sinclude\((.*)\)/ && -f ($rd . $1)) { $ff = $rd . $1; scan_one_configure_file ($ff, $rd); } if (! $in_ac_output && ( s/AC_OUTPUT\s*\(\[?// || s/AC_CONFIG_FILES\s*\(\[?// ) ) { $in_ac_output = 1; $ac_output_line = $.; # get LINE number prt( "Got ac_output_line = [$ac_output_line] ...\n" ) if ($dbg4); } if ($in_ac_output) { my $closing = 0; if (s/[\]\),].*$//) { $in_ac_output = 0; $closing = 1; } # Look at potential Makefile.am's foreach (split) { # Must skip empty string for Perl 4. next if $_ eq "\\" || $_ eq ''; my ($local,$input,@rest) = split(/:/); if (! $input) { $input = $local; } else { $input =~ s/\.in$//; } $ff = $rd . $input . '.am'; if (-f $ff) { prt( "Adding $input [$ff] to make_input_list ...\n" ) if ($dbg5); push(@make_input_list, $input); $make_list{$input} = join(':', ($local,@rest)); } else { prt( "Adding $input [$ff] to other_input_files ...\n" ) if ($dbg5); # We have a file that automake should cause to be # rebuilt, but shouldn't generate itself. push (@other_input_files, $_); } } } # Handle configuration headers. A config header of `[$1]' # means we are actually scanning AM_CONFIG_HEADER from # aclocal.m4. if (/A([CM])_CONFIG_HEADER\s*\((.*)\)/ && $2 ne '[$1]') { am_conf_line_error($filename, $., "automake requires AM_CONFIG_HEADER, not AC_CONFIG_HEADER") if $1 eq 'C'; $config_header_line = $.; my ($one_hdr); foreach $one_hdr (split (' ', $2)) { push (@config_fullnames, $one_hdr); if ($one_hdr =~ /^([^:]+):(.+)$/) { push (@config_names, $1); push (@config_headers, $2); } else { push (@config_names, $one_hdr); push (@config_headers, $one_hdr . '.in'); } } } if (/$AM_CONDITIONAL_PATTERN/o) { prt( "$aclnum: [$acline]\n" ) if ($dbg2a); if ( defined $cfg_defines{$1} ) { # has been DEFINED in am2dsp?.cfg file, or previously defined prt( "Storing configure_cond key $1 ... value=2\n" ) if ($dbg2); $configure_cond{$1} = 2; } else { prt( "Storing configure_cond key $1 ... value=1\n" ) if ($dbg2); $configure_cond{$1} = 1; } } if (/$AM_INIT_AUTOMAKE/o) { $dsp_package = $1; $dsp_version = $2; prt( "Got AM_INIT_AUTOMAKE($dsp_package, $dsp_version) ...\n" ); $dsp_package = do_macro_sub($dsp_package); $dsp_version = do_macro_sub($dsp_version); prt( "Set DSP package = $dsp_package, DSP version = $dsp_version ...\n" ); } } close(CONFIGURE); } sub am_error { my ($msg) = shift; prt( $msg."\n" ); close_log($outfile,1); exit($exit_status); } sub am_conf_line_error { my (@args) = @_; am_error(join(' ',@args)); } sub am_line_error { my ($symbol, @args) = @_; prt( "am_line_error: sym=[$symbol] arg0=[$args[0]] ...\n" ); if ($symbol && "$symbol" ne '-1') { my ($file) = "$active_am_file"; if ($symbol =~ /^\d+$/) { # SYMBOL is a line number, so just add the colon. $file .= ':' . $symbol; } elsif (defined $content_lines{$symbol}) { # SYMBOL is a variable defined in Makefile.am, so add the # line number we saved from there. $file .= ':' . $content_lines{$symbol}; } elsif (defined $configure_vars{$symbol}) { # SYMBOL is a variable defined in configure.ac, so add the # appropriate line number. $file = $configure_vars{$symbol}; } else { # Couldn't find the line number. } ###warn $file, ": ", join (' ', @args), "\n"; prt( "$file: ". join (' ', @args). "\n" ); $exit_status = 1; prt( "ERROR EXIT!\n" ); close_log($outfile,1); exit($exit_status); } else { am_error (join(' ',@args)); } } sub initialize_per_input { # These two variables are used when generating each Makefile.in. # They hold the Makefile.in until it is ready to be printed. $output_vars = ''; $output_trailer = ''; # This holds the contents of a Makefile.am, as parsed by # read_am_file. %contents = (); # This holds the names which are targets. These also appear in # %contents. %targets = (); # For a variable or target which is defined conditionally, this # holds an array of the conditional values. The array is composed # of pairs of condition strings (the variables which configure # will substitute) and values (the value of a target is # meaningless). For an unconditional variable, this is empty. %conditional = (); # This holds the line numbers at which various elements of # %contents are defined. %content_lines = (); # This holds a 1 if a particular variable was examined. %content_seen = (); # This is the conditional stack. @conditional_stack = (); # This holds the set of included files. @include_stack = (); # This holds the "relative directory" of the current Makefile.in. # Eg for src/Makefile.in, this is "src". $relative_dir = ''; # This maps the source extension of a suffix rule to its # corresponding output extension. %suffix_rules = (); # per AM file sources @am_c_files = (); @am_h_files = (); @am_o_files = (); } sub unique_proj { my ($prj) = shift; if (defined $other_projs{$prj}) { my $nprj = $prj; my $i = 0; while (defined $other_projs{$nprj}) { $i++; $nprj = "$prj$i"; } return $nprj; } return $prj; } sub get_lib_depends($) { my ($deps) = shift; # = ($contents{$ky}); # like bvhtest_LDADD = libsgbvh.a -lsgstructure -lsgmath $(base_LIBS) # [openal_test1]=[$(top_builddir)/simgear/debug/libsgdebug.a $(openal_LIBS)] my @arr = split(' ',$deps); my $srcs = ''; my ($fi,$fil,$dir); foreach $fi (@arr) { $fi = substr($fi,16) if ($fi =~ /^\$\(top_builddir\)\//); # remove top_builddir... next if ($fi =~ /^\$\(\w+\)$/); # for the moment IGNORE '$(base_LIBS)', '$(openal_LIBS)'... ($fil,$dir) = fileparse($fi); # only want filename at end if ($fil =~ /^lib(\w+)\.a$/) { $fil = $1; # chop off 'lib(.+).a' } elsif ($fil =~ /^-l/) { $fil = substr($fil,2); # remove '-l' at front } else { prtw("WARNING: get_lib_depends: CHECKOUT this item [$fi] [$fil]!!!\n"); $fil = ''; } if (length($fil)) { next if ($fil eq 'z'); # forget libz next if ($fil eq 'stdc++'); # and stdc $srcs .= "*" if (length($srcs)); # add separator $srcs .= $fil; # and this item } } return $srcs; # return LIST } # process for OTHER THAN LIBRARIES sub process_other_sources { my ($mf, $rd) = @_; my ($nam, $dir, $ext) = fileparse( $mf, qr/\.[^.]*/ ); my $rel_dir = dirname($mf); # like 'noinst_PROGRAMS = calc_loc' # and then 'calc_loc_SOURCES = calc_loc.cxx' my ($key, $projs, $proj, $proj2, $ky, $fnd, $skey, $fil, $srcs, $fi, $dnmf, $dndir, $uproj); my ($typ, $proj3); my $bas_dir = ".\\"; my @dir_cont = (); my @proj_arr = (); my @proj_files = (); $fnd = 0; $dnmf = 0; foreach $key (keys %contents) { $projs = $contents{$key}; # get PROJECT name #if (($key eq 'noinst_PROGRAMS')||($key eq 'bin_PROGRAMS')) { if ( $key =~ /(.+)_PROGRAMS/) { $typ = $1; # usually 'noinst' or 'bin', but ... @proj_arr = split(' ', $projs); # split in case multiple foreach $proj (@proj_arr) { # process each project, getting the SOURCES $proj2 = $proj; $proj2 =~ s/-/_/g; # change hyphen (-) to underscore (_) foreach $ky (keys %contents) { if (($ky =~ /($proj)_SOURCES/) || ($ky =~ /($proj2)_SOURCES/)){ $skey = $ky; $fnd = 1; last; } } if ($fnd) { @proj_files = split(' ', $contents{$skey}); #prt( "Project: [$proj] - sources [".$contents{$skey}."]\n" ); $srcs = ''; foreach $fil (@proj_files) { if ($fil =~ /^\$\(([^\)]*)\)$/) { # Found a variable. my $varname = $1; if (defined $contents{$varname}) { my @f2 = split(' ', $contents{$varname}); foreach $fi (@f2) { $srcs .= '*' if (length($srcs)); $srcs .= unix_2_dos($bas_dir . $rel_dir . "\\" . $fi); } } else { $srcs .= '*' if (length($srcs)); $srcs .= unix_2_dos($bas_dir . $rel_dir . "\\" . $fil); } } else { $srcs .= '*' if (length($srcs)); $srcs .= unix_2_dos($bas_dir . $rel_dir . "\\" . $fil); } } prt( "Project: [$proj] - sources [$srcs]\n" ) if ($dbg21); $uproj = unique_proj($proj); $other_projs{$uproj} = $srcs; # keep this PROJECT, and SOURCES (both c and h) find_am_includes( $proj, $uproj, $rd ); foreach $ky (keys %contents) { if (($ky =~ /($proj)_LDADD/) || ($ky =~ /($proj2)_LDADD/)){ $srcs = get_lib_depends($contents{$ky}); if (length($srcs)) { $other_deps{$uproj} = $srcs; prt("[dbg29] Found dependencies [$uproj]=[$srcs].\n") if ($dbg29); } last; } } } else { prtw("WARNING: Using a LOOSE search, since [$proj] nor [$proj2]_SOURCES NOT FOUNT!\n"); # so, just search for SOURCES - may be a MACRO, which did not expand!!! foreach $ky (keys %contents) { if ($ky =~ /(.+)_SOURCES/) { $proj3 = $1; # maybe this is the PROJECT name $skey = $ky; $fnd = 1; last; } } if ($fnd) { @proj_files = split(' ', $contents{$skey}); #prt( "Project: [$proj] - sources [".$contents{$skey}."]\n" ); $srcs = ''; foreach $fil (@proj_files) { if ($fil =~ /^\$\(([^\)]*)\)$/) { # Found a variable. my $varname = $1; if (defined $contents{$varname}) { my @f2 = split(' ', $contents{$varname}); foreach $fi (@f2) { $srcs .= '*' if (length($srcs)); $srcs .= unix_2_dos($bas_dir . $rel_dir . "\\" . $fi); } } else { $srcs .= '*' if (length($srcs)); $srcs .= unix_2_dos($bas_dir . $rel_dir . "\\" . $fil); } } else { $srcs .= '*' if (length($srcs)); $srcs .= unix_2_dos($bas_dir . $rel_dir . "\\" . $fil); } } prt( "Project: [$proj] - sources [$srcs]\n" ) if ($dbg21); $uproj = unique_proj($proj3); $other_projs{$uproj} = $srcs; # keep this PROJECT, and SOURCES (both c and h) find_am_includes( $proj3, $uproj, $rd ); } else { # if we can FIND a C source in the folder OF THE SAME NAME # as this project if ( !$dndir ) { prtw("WARNING: Even LOOSE search FAILED for [$proj] and [$proj2] READING DIRECTORY!\n"); $fil = $rd . $rel_dir; if (opendir( DIR, $fil)) { @dir_cont = readdir(DIR); close DIR; prt( "Found ".scalar @dir_cont." items in [$fil]\n" ) if ($dbg23); } else { prtw( "WARNING: FAILED to OPEN DIRECTORY [$fil] ...\n" ); } $dndir = 1; } $srcs = ''; $fnd = 0; if ( @dir_cont ) { # check contents of local directory foreach $fi (@dir_cont) { next if (($fi eq '.')||($fi eq '..')); $fil = $rd . $rel_dir . "\\" . $fi; if ( is_c_source($fi) && (-f $fil)) { if ($fi =~ /$proj\..+/) { $srcs = unix_2_dos($rel_dir . "\\" . $fi); $fnd = 1; last; } } } } if ($fnd) { prt( "Project: [$proj] - sources [$srcs]\n" ) if ($dbg21 || $dbg23); $uproj = unique_proj($proj); $other_projs{$uproj} = $srcs; # keep this PROJECT $fnd = 0; find_am_includes( $proj, $uproj, $rd ); } else { prt( "Processing file [$mf] ...\n" ) if (!$dnmf); if ($proj =~ /^\@.+\@$/) { $proj = substr($proj,1,length($proj)-2); my $msub = do_macro_sub2($proj); prtw( "WARNING: Project: @[$proj]@ = [$msub] - NO SOURCES FOUND???\n" ); } else { prtw( "WARNING: Project: [$proj] - NO SOURCES FOUND???\n" ); } $dnmf = 1; } } } } # for each $proj in @proj_arr - that is EACH PROGRAM } # if ( $key =~ /(.+)_PROGRAMS/) } # for each key in the Makefile.am file - key = something } sub replace_top_srcdir { my ($nam,$rd) = @_; if ($nam =~ /\$\(([^\)]*)\)/ ) { my $mac = $1; prt( "Checking [$mac] ...\n" ) if ($dbg25); if (($mac eq 'top_srcdir') || ($mac eq 'top_builddir') ) { $nam =~ s/\$\(${mac}\)/$rd/; $nam = unix_2_dos($nam); $nam =~ s/\\{2}/\\/g; prt( "Substituted [$nam] ...\n" ) if ($dbg25); } } return $nam; } sub find_am_includes { my ( $proj, $group, $rd ) = @_; ### FIND INCLUDES ################# # like INCLUDES = -I$(top_srcdir)/include my $incs = ''; my @files = (); my $cnt = 0; my $nam = ''; my $mac = ''; my $ii = 0; my $jj = 0; my $k2 = ''; foreach $k2 (keys %contents) { if ($k2 eq 'INCLUDES') { $incs = $contents{$k2}; last; } } $incs = trim_all($incs); if (length($incs)) { prt( "Got INCLUDES [$incs] ...\n" ) if ($dbg25); @files = split(' ',$incs); $cnt = scalar @files; for ($ii = 0; $ii < $cnt; $ii++) { $nam = $files[$ii]; $nam =~ s/^-I//; $nam = replace_top_srcdir($nam,$rd); $files[$ii] = $nam; } # remove any DUPLICATES for ($ii = 0; $ii < $cnt; $ii++) { $nam = $files[$ii]; if (length($nam)) { for ($jj = 0; $jj < $cnt; $jj++) { if ($ii != $jj) { if ($nam eq $files[$jj]) { $files[$jj] = ''; } } } } } $incs = join(' ', @files); } $am_includes{$group} = $incs; prt( "[dbg26] For $group, saved INCLUDES [$incs]\n" ) if ($dbg26); # STATICCPPFLAGS = -DCURL_STATICLIB # CPPFLAGS = -DCURL_NO_OLDIES $(STATICCPPFLAGS) $incs = ''; foreach $k2 (keys %contents) { if ($k2 eq 'CPPFLAGS') { $incs = $contents{$k2}; last; } } $incs = trim_all($incs); if (length($incs)) { prt( "Got CPPFLAGS [$incs] ...\n" ) if ($dbg25); @files = split(' ',$incs); $cnt = scalar @files; for ($ii = 0; $ii < $cnt; $ii++) { $nam = $files[$ii]; $nam =~ s/^-D//; if ($nam =~ /\$\(([^\)]*)\)/ ) { $mac = $1; prt( "Checking [$mac] ...\n" ) if ($dbg25); if (defined $contents{$mac}) { my $mac2 = $contents{$mac}; $nam =~ s/\$\(${mac}\)/$mac2/; $nam =~ s/^-D//; prt( "Substituted [$nam] ...\n" ) if ($dbg25); } } $files[$ii] = $nam; } $incs = join(' ', @files); } prt( "[dbg26] For $group, saved CPPFLAGS [$incs]\n" ) if ($dbg26); $am_cppflags{$group} = $incs; # LIBDIR = $(top_builddir)/lib # LDADD = $(LIBDIR)/libcurl.la $incs = ''; foreach $k2 (keys %contents) { #if ($k2 eq 'LDADD') { if ($k2 =~ /LDADD/) { $incs = $contents{$k2}; last; } } $incs = trim_all($incs); if (length($incs)) { prt( "Got LDADD [$incs] ...\n" ) if ($dbg25); @files = split(' ',$incs); $cnt = scalar @files; for ($ii = 0; $ii < $cnt; $ii++) { $nam = $files[$ii]; $nam =~ s/^-I//; if ($nam =~ /\$\(([^\)]*)\)/ ) { $mac = $1; prt( "Checking [$mac] ...\n" ) if ($dbg25); if (defined $contents{$mac}) { my $mac2 = $contents{$mac}; $mac2 = replace_top_srcdir($mac2,$rd); $nam =~ s/\$\(${mac}\)/$mac2/; $nam = unix_2_dos($nam); if ($nam =~ /lib(\w+)\.la/) { $nam =~ s/lib(\w+)\.la/Lib_${1}\.lib/; } prt( "Substituted [$nam] ...\n" ) if ($dbg25); } } $files[$ii] = $nam; } $incs = join(' ', @files); } prt( "[dbg26] For $group, saved LDADD [$incs]\n" ) if ($dbg26); $am_libadds{$group} = $incs; } sub process_am_file { my ($dsp_name,$makefile,$rd) = @_; my $base_dir = './'; my $dsp_file = $rd . $dsp_name . '.dsp'; prt( "process_am_file: using dsp_name=$dsp_file, and makefile=$makefile ...\n" ) if $dbg7; initialize_per_input(); ###my $relative_dir = dirname($makefile); $relative_dir = dirname($makefile); my $dupe = 0; my @files = (); my $key = ''; my $group = 'Lib_Special'; my $file = ''; # full path to file my $fi = ''; # filename only my $ext = ''; # and its extension my $dir = ''; # directory it is in my $nam = ''; # file title my $proj = ''; my $cnt = 0; my $fnd = 0; my $gotsubd = 0; my $gotinch = 0; # build AM file name my $file_am = $rd . $makefile; # 04/04/2008 READ 'configure.ac' if present in THIS DIRECTORY # =========================================================== my $file_ac = $full_fil_path . "configure.ac"; if ( -f $file_ac ) { # we have an configure.ac file here scan_one_configure_file( $file_ac, $rd ); } $file_am .= '.am' if !($file_am =~ /\.am$/i); $current_am_file = sub_common_folder($file_am,$rd); prt( "Processing AM file [$current_am_file]\n" ) if ($dbg24); push(@done_am,$file_am); read_main_am_file($file_am, $rd); # preview the 'contents' to find 'group' if ($dbg28 || $dbg19) { $cnt = scalar keys(%contents); prt( "CT: Got $cnt items in \%contents ... file $file_am ...\n" ); $cnt = 0; foreach $key (keys %contents) { $file = trim_all($contents{$key}); $cnt++; prt( "CT:$cnt: [$key] = [$file]\n" ); } } ############################################################### ## process various contents of %contents ############################################################## # use 'noinst_LIBRARIES' macro foreach $key (keys %contents) { #if ($key eq 'noinst_LIBRARIES') { if ($key =~ /\s*([\w-]+)_LIBRARIES\s*/) { @files = split(' ', $contents{$key}); foreach $file (@files) { if ($file =~ /^lib([\w-]+)\.a/) { $group = 'lib' . $1; prt( "Group set to [$group] ... file $file_am ...\n" ) if ($dbg8 || $dbg8g); $fnd = 1; last; } } } elsif ($key eq 'SUBDIRS') { $gotsubd++; } elsif ($key eq 'include_HEADERS') { $gotinch++; } } if (!$fnd) { # found NOT LIBRARY item # try for check_PROGRAMS or bin_PROGRAMS foreach $key (keys %contents) { if ($key =~ /\s*([\w-]+)_PROGRAMS\s*/) { $nam = $1; @files = split(' ', $contents{$key}); foreach $file (@files) { if ($file =~ /^([\w-]+)$/) { ###$group = $nam.'_'. $1; $group = $1; prt( "Group set to [$group] ... file $file_am ...\n" ) if ($dbg8 || $dbg8g); $fnd = 1; last; } } } } } # 10/02/2010 - NO warning IF it has a 'SUBDIRS' entry if (!$fnd && ($gotsubd == 0) && ($gotinch == 0)) { #if (!$fnd) { prtw( "WARNING: NO 'GROUP' FOUND in $file_am ...\n" ); } else { } # now extract LIBRARY SOURCES from 'contents' hash foreach $key (sort keys %contents) { #if ($key eq "include_HEADERS") { #} # not found in Makefile.am files? #if ($key =~ /^lib(.*)_a_SOURCES/) { #if (($key =~ /^lib(.*)_a_SOURCES/) || # ($key =~ /^lib(.*)_la_SOURCES/) || # ($key =~ /^libc(.*)_la_SOURCES/) ) { if (($key =~ /lib(.*)_a_SOURCES/) || ($key =~ /lib(.*)_la_SOURCES/) || ($key =~ /libc(.*)_la_SOURCES/) ) { $proj = $1; # keep Project RAW name $group = 'lib' . $proj; # generate a GROUP @files = split(' ', $contents{$key}); foreach (@files) { my $src_dir = $base_dir . $relative_dir . '/'; $src_dir =~ s/\//\\/g; # fixup DOS path separators if (/^\$\(([^\)]*)\)$/) { # Found a variable. my $varname = $1; prt( "Expanding variable $varname ...\n" ) if ($dbg8); foreach (split(' ', $contents{$varname})) { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); } prt( "Done expanding variable $varname ...\n" ) if ($dbg8); } else { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); } } find_am_includes( $proj, $group, $rd ); } elsif ($key eq "fgfs_SOURCES") { #elsif ($key =~ /(.*)_SOURCES/) { $group = 'main'; @files = split(' ', $contents{$key}); foreach $fi (@files) { my $sdir = $base_dir . $relative_dir . '/'; $sdir =~ s/\//\\/g; # fixup DOS path separators $file = $sdir . $fi; $dupe = add_2_source_list( $file, $group ); } } else { # key is NOT ( Lib(.*)_a_SOURCES fgfs_SOURCES ) if (($key eq 'EXTRA_DIST')||($key eq 'fgjs_SOURCES')) { @files = split(' ', $contents{$key}); foreach $fi (@files) { ($nam, $dir, $ext) = fileparse( $fi, qr/\.[^.]*/ ); $file = $base_dir . $relative_dir . '/' . $fi; $file =~ s/\//\\/g; # use DOS path sep if (is_c_source_ext($ext)) { push(@msvc_c_extra, $file); prt( "Added [$file] to C EXTRA list\n" ) if $dbg9; } elsif (is_h_source_ext($ext)) { push(@msvc_h_extra, $file); prt( "Added [$file] to H EXTRA list\n" ) if $dbg9; } else { push(@msvc_o_extra, $file); prt( "Added [$file] to other EXTRA list\n" ) if $dbg9; } } } elsif ($key eq 'noinst_HEADERS') { # JSBSim has put the HEADERS in HERE, # FIX20061107 # more recently SimGear put some 'source' file in here # which are now discarded @files = split(' ', $contents{$key}); foreach $fi (@files) { ($nam, $dir, $ext) = fileparse( $fi, qr/\.[^.]*/ ); if (is_h_source_ext($ext)) { # FIX20061107 - only IFF a header $file = $base_dir . $relative_dir . '/' . $fi; $file =~ s/\//\\/g; # use DOS path sep $dupe = add_2_source_list( $file, $group ); } } } } } # process for OTHER THAN LIBRARIES process_other_sources( $makefile . '.am', $rd ); # per AM file sources my $ac_cnt = scalar @am_c_files; my $ah_cnt = scalar @am_h_files; my $of_cnt = scalar @am_o_files; ###prt( "End am file: $dsp_file - ac_cnt=$ac_cnt, ah_cnt=$ah_cnt, from $makefile.am ...\n" ) if ($dbg20); prt( "End_am_file: ac_cnt=$ac_cnt, ah_cnt=$ah_cnt, of_cnt=$of_cnt, from $makefile ...\n" ) if ($dbg20); } sub read_main_am_file { my ($amfile, $rd) = @_; read_am_file($amfile, $rd); my @topdir = (); foreach (split(/\//, $relative_dir)) { next if $_ eq '.' || $_ eq ''; if ($_ eq '..') { pop @topdir; } else { push(@topdir, '..'); } } @topdir = ('.') if ! @topdir; my $top_builddir = join('/', @topdir); } sub read_am_file { my ($am_file, $rd) = @_; $active_am_file = $am_file; ###open( AM_FILE, $am_file ) or mydie( "ERROR: Can't open $am_file: $!\n" ); ###if ($am_file =~ /^(\\|\/){1}/) { ### $am_file = substr($am_file,1); ###} if (!open( AM_FILE, $am_file )) { prtw( "ERROR: Can't open $am_file: $! \n" ); return; } prt( "\n$pack: reading $am_file (rel_dir=$relative_dir)\n" ) if ($dbg10 || $dbg16 || $dbg19); my @am_lines = <AM_FILE>; close AM_FILE; my $am_lncnt = scalar @am_lines; my ($am_name, $am_path) = fileparse($am_file); my $saw_bk = 0; my $was_rule = 0; my $spacing = ''; my $comment = ''; my $last_var_name = ''; my $blank = 0; my $cond_true = 2; # undetermined ... my $msg = ''; my $aml = ''; my $aln = 0; my $ai = 0; my $cond_string = ''; # process, line by line ... where $aln is current line for ($ai = 0; $ai < $am_lncnt; $ai++) { $_ = $am_lines[$ai]; $aln = $ai + 1; if (/$IGNORE_PATTERN/o) { # Merely delete comments beginning with two hashes. } elsif (/$WHITE_PATTERN/o) { # Stick a single white line before the incoming macro or rule. $spacing = "\n"; $blank = 1; } elsif (/$COMMENT_PATTERN/o) { # Stick comments before the incoming macro or rule. Make # sure a blank line preceeds first block of comments. $spacing = "\n" unless $blank; $blank = 1; $comment .= $spacing . $_; $spacing = ''; } else { last; } } $output_vars .= $comment . "\n"; $comment = ''; $spacing = "\n"; my $source_suffix_pattern = ''; my $is_ok_macro = 0; for ( ; $ai < $am_lncnt; $ai++) { $_ = $am_lines[$ai]; $aln = $ai + 1; $aml = $am_lines[$ai]; chomp $aml; $aml = trim_all($aml); # clean up line prt( "$aln [$aml]\n" ) if ($dbg10); $_ .= "\n" unless substr ($_, -1, 1) eq "\n"; if (/$IGNORE_PATTERN/o) { # Merely delete comments beginning with two hashes. } elsif (/$WHITE_PATTERN/o) { # Stick a single white line before the incoming macro or rule. $spacing = "\n"; ###am_line_error ($., "blank line following trailing backslash") if $saw_bk; am_line_error ($aln, "blank line following trailing backslash") if $saw_bk; } elsif (/$COMMENT_PATTERN/o) { # Stick comments before the incoming macro or rule. $comment .= $spacing . $_; $spacing = ''; ###am_line_error ($., "comment following trailing backslash") if $saw_bk; am_line_error ($aln, "comment following trailing backslash") if $saw_bk; } elsif ($saw_bk) { # continuation of previous line(s) ... if ($was_rule) { $output_trailer .= join ('', @conditional_stack) . $_; $saw_bk = /\\$/; } else { $saw_bk = /\\$/; # Chop newline and backslash if this line is # continued. ensure trailing whitespace exists. chop if $saw_bk; chop if $saw_bk; # decide if to be added to 'contents' ... my $add_it = 0; # assume NO my $disc_it = 0; # also NO if ( defined $contents{$last_var_name} ) { if ( @conditional_stack ) { if ( $conditional_stack[$#conditional_stack] =~ /_TRUE\@$/ ) { # we are in the if TRUE state if ($cond_true == 1) { $add_it = 1; } else { $disc_it = 1; } } else { # we are in a FALSE state if ($cond_true != 1) { $add_it = 1; } else { $disc_it = 1; } } } else { ###prt( "No conditional stack for this macro! lv=[$last_var_name] ". ### "add_it\n" ) if ($dbg11); $add_it = 1; # so add it } } else { # NO contents for this var prt( "NO contents for [$last_var_name]! ". "Technical this is an ERROR, but for now add_it...\n" ) if ($dbg11); $add_it = 1; } if ($add_it) { $contents{$last_var_name} .= ' ' unless $contents{$last_var_name} =~ /\s$/; $contents{$last_var_name} .= $_; if (@conditional_stack) { $conditional{$last_var_name} .= quote_cond_val ($_); } prt( "End $last_var_name = [".trim_line($contents{$last_var_name})."]...\n" ) if ( ! $saw_bk && $dbg12); } else { if ($dbg22 || !$disc_it) { # that is, if NOT a deliberate discard ###push(@warnings, "WARNING: File [$am_file], line $., last var [$last_var_name]"); push(@warnings, "WARNING: File [$am_file], line $aln, last var [$last_var_name]"); push(@warnings, " Discarding the [$_] ... CHECK ME"); if ( defined $contents{$last_var_name} ) { if ( @conditional_stack ) { push(@warnings, " stack = $conditional_stack[$#conditional_stack] cond_true=$cond_true"); } } prtw( "WARNING: Discarding this [$_] ... CHECK ME!\n" ); } } } } elsif (/$IF_PATTERN/o) { if ( defined $configure_cond{$1} ) { ###if ( defined $cfg_defines{$1} ) if ($configure_cond{$1} == 2) { prt( "Found if $1, and condition is TRUE (see cfg_defines) ...\n" ) if ($dbg13); $cond_true = 1; } else { prt( "Found if $1, but NOT in cfg_defines ...\n" ) if ($dbg13); $cond_true = 0; } } else { # 2009-06-09 - change to a WARNING only ###am_line_error ($aln, "Line $aln: [$aml]\n[$1] does not appear in AM_CONDITIONAL!"); prtw("WARNING: Line $aln: [$aml] [$1] does not appear in AM_CONDITIONAL!\n"); } push (@conditional_stack, "\@" . $1 . "_TRUE\@"); } elsif (/$ELSE_PATTERN/o) { if (! @conditional_stack) { ###am_line_error ($., "else without if"); am_line_error ($aln, "else without if"); } elsif ($conditional_stack[$#conditional_stack] =~ /_FALSE\@$/) { ###am_line_error ($., "else after else"); am_line_error ($aln, "else after else"); } else { $conditional_stack[$#conditional_stack] =~ s/_TRUE\@$/_FALSE\@/; } } elsif (/$ENDIF_PATTERN/o) { if (! @conditional_stack) { ###am_line_error ($., ": endif without if"); am_line_error ($aln, ": endif without if"); } else { pop @conditional_stack; } $cond_true = 2; # undetermined ... } elsif (/$RULE_PATTERN/o) { # Found a rule. $was_rule = 1; if (defined $contents{$1} && (@conditional_stack ? ! defined $conditional{$1} : defined $conditional{$1})) { am_line_error ($1, "$aln: $1 if RULE_PATTERN defined both conditionally and unconditionally"); } # Value here doesn't matter; for targets we only note # existence. $contents{$1} = 1; $targets{$1} = 1; $cond_string = join ('', @conditional_stack); if (@conditional_stack) { if ($conditional{$1}) { check_ambiguous_conditional ($1, $cond_string); $conditional{$1} .= ' '; } else { $conditional{$1} = ''; } $conditional{$1} .= $cond_string . ' 1'; } ###$content_lines{$1} = $.; $content_lines{$1} = $aln; $output_trailer .= $comment . $spacing . $cond_string . $_; $comment = $spacing = ''; $saw_bk = /\\$/; # Check the rule for being a suffix rule. If so, store in # a hash. my $source_suffix; my $object_suffix; if (($source_suffix, $object_suffix) = ($1 =~ $SUFFIX_RULE_PATTERN)) { $suffix_rules{$source_suffix} = $object_suffix; prt( "Sources ending in .$source_suffix become .$object_suffix\n" ) if $dbg17; $source_suffix_pattern = "(" . join('|', keys %suffix_rules) . ")"; } # FIXME: make sure both suffixes are in SUFFIXES? Or set # SUFFIXES from suffix_rules? } elsif (($is_ok_macro = /$MACRO_PATTERN/o) || /$BOGUS_MACRO_PATTERN/o) { prt( "line $aln: Found a macro definition. 1[$1] 2[$2] 3[$3] ...\n" ) if ($dbg14); $was_rule = 0; $last_var_name = $1; my $type = $2; my $value = $3; if (defined $contents{$1} && (@conditional_stack ? !defined $conditional{$1} : defined $conditional{$1})) { prt( "POTENTIAL ERROR: Found a macro definition. 1[$last_var_name] 2[$type] 3[$value] ...\n" ); if (@conditional_stack) { prt( "Conditional stack: $conditional_stack[-1]" ); } else { prt( "NO Conditional stack: " ); } if (defined $conditional{$last_var_name}) { prt( " Value = $conditional{$last_var_name}" ); } else { prt( " No conditional" ); } prt(" IGNORED\n"); #am_line_error ($last_var_name, "$last_var_name $aln: if MACRO_PATTERN defined both conditionally and unconditionally"); } if (($value ne '') && (substr($value, -1) eq "\\")) { $value = substr($value, 0, length($value) - 1); } #else { # $value = $3; #} if ($type eq '+') { if (! defined $contents{$last_var_name} && defined $configure_vars{$last_var_name}) { $contents{$last_var_name} = '@' . $last_var_name . '@'; } $contents{$last_var_name} .= ' ' . $value; } else { if ( defined $contents{$last_var_name} ) { if ( @conditional_stack ) { if ( $conditional_stack[$#conditional_stack] =~ /_TRUE\@$/ ) { # we are in the if TRUE state if ($cond_true == 1) { if ($dbg15) { if ( $contents{$last_var_name} ne $value ) { ### " replaced with [$value] (am_file=$am_file line=$.)". prt( "NB: [$last_var_name] = [$contents{$last_var_name}]" . " replaced with [$value] (am_file=$am_file line=$aln)". (/\\$/ ? "saw_bk" : "end") . "\n" ); } } $contents{$last_var_name} = $value; ###$content_lines{$last_var_name} = $.; $content_lines{$last_var_name} = $aln; } } else { # we are in the else FALSE state if ($cond_true != 1) { if ($dbg15) { if ( $contents{$last_var_name} ne $value ) { ### " replaced with [$value] (am_file=$am_file line=$.)". prt( "NB: [$last_var_name] = [$contents{$last_var_name}]" . " replaced with [$value] (am_file=$am_file line=$aln)". (/\\$/ ? "saw_bk" : "end") . "\n" ); } } $contents{$last_var_name} = $value; ###$content_lines{$last_var_name} = $.; $content_lines{$last_var_name} = $aln; } } } } else { ### "(am_file=$am_file line=$.) ". prt( "First setting [$last_var_name] = [$value] " . "(am_file=$am_file line=$aln) ". (/\\$/ ? "saw_bk" : "end") . "\n" ) if ($dbg15); $contents{$last_var_name} = $value; # The first assignment to a macro sets the line # number. Ideally I suppose we would associate line # numbers with random bits of text. ###$content_lines{$last_var_name} = $.; $content_lines{$last_var_name} = $aln; } } $cond_string = join ('', @conditional_stack); if (@conditional_stack) { my $found = 0; my $val; if ($conditional{$last_var_name}) { if ($type eq '+') { # If we're adding to the conditional, and it # exists, then we might want to simply replace # the old value with the new one. my (@new_vals, @cond_vals); @cond_vals = split (' ', $conditional{$last_var_name}); while (@cond_vals) { my $vcond = shift (@cond_vals); push (@new_vals, $vcond); if (conditional_same ($vcond, $cond_string)) { $found = 1; $val = (unquote_cond_val (shift (@cond_vals)) . ' ' . $value); push (@new_vals, quote_cond_val ($val)); } else { push (@new_vals, shift (@cond_vals)); } } if ($found) { $conditional{$last_var_name} = join (' ', @new_vals); } } if (! $found) { check_ambiguous_conditional ($last_var_name, $cond_string); $conditional{$last_var_name} .= ' '; $val = $value; } } else { $conditional{$last_var_name} = ''; $val = $contents{$last_var_name}; } if (! $found) { $conditional{$last_var_name} .= ($cond_string . ' ' . quote_cond_val ($val)); } } # FIXME: this doesn't always work correctly; it will group # all comments for a given variable, no matter where # defined. $am_vars{$last_var_name} = $comment . $spacing; $def_type{$last_var_name} = ($type eq ':') ? ':' : ''; push (@var_list, $last_var_name); $comment = $spacing = ''; $saw_bk = /\\$/; # Error if bogus. ###am_line_error ($., "bad macro name \`$last_var_name'") if ! $is_ok_macro; am_line_error ($aln, "bad macro name \`$last_var_name'") if ! $is_ok_macro; } elsif (/$INCLUDE_PATTERN/o) { my $orgpath = $1; my $path = $orgpath; if ($path =~ s/^\$\(top_srcdir\)\///) { push (@include_stack, "\$\(top_srcdir\)/$path"); } else { $path =~ s/\$\(srcdir\)\///; push (@include_stack, "\$\(srcdir\)/$path"); $path = $relative_dir . "/" . $path; } if ($path =~ /^\//) { $path = substr($path,1); } if (! -f $path) { my $ff = $relative_dir . "/" . $path; if (-f $ff) { $path = $ff; } else { $ff = $rd . $path; if (-f $ff) { $path = $ff; } else { prtw( "WARNING: in [$am_file] - Include WILL FAIL! [$orgpath] ...\n" ); prtw( " Last try was $ff ...\n" ); } } } read_am_file ($path, $rd); $active_am_file = $am_file; } else { # This isn't an error; it is probably a continued rule. # In fact, this is what we assume. $was_rule = 1; $output_trailer .= ($comment . $spacing . join ('', @conditional_stack) . $_); $comment = $spacing = ''; $saw_bk = /\\$/; } ###$_ = <AM_FILE>; } prt( "Done reading of $am_file\n" ) if ($dbg10 || $dbg16 || $dbg19); ###close(AM_FILE); $output_trailer .= $comment; am_error ("unterminated conditionals: " . join (' ', @conditional_stack)) if (@conditional_stack); } sub add_2_source_list { my ($fil, $grp) = @_; my ($ft, $dir, $fe) = fileparse( $fil, qr/\.[^.]*/ ); my $src = ($grp . '|' . $fil . '|' . $ft); my $ret = 0; if ( is_c_source_ext($fe) ) { prt( "Add $src to C list\n" ) if $dbg18; push(@msvc_c_files, $src); foreach my $tt (@msvc_titles) { # just to deal with duplicate names if( $tt eq $ft ) { $ret = 1; last; } } push(@msvc_titles, $ft); push(@am_c_files, $src); } elsif ( is_h_source_ext($fe) ) { prt( "Add $src to H list\n" ) if $dbg18; push(@msvc_h_files, $src); push(@am_h_files, $src); } else { prt( "Add $src to OTHER list\n" ) if $dbg18; push(@msvc_o_files, $src); push(@am_o_files, $src); } return $ret; } # Quote a value in order to put it in $conditional. We need to quote # spaces, and we need to handle null strings, so that we can later # retrieve values by splitting on space. sub quote_cond_val { my ($val) = @_; $val =~ s/ /\001/g; $val =~ s/\t/\003/g; $val = "\002" if $val eq ''; return $val; } # this function seems MISSING - maybe never used! sub unquote_cond_val { my ($val) = @_; $val =~ s/\001/ /g; $val =~ s/\003/\t/g; $val = '' if $val eq "\002"; return $val; } # See if a conditional is true. Both arguments are conditional # strings. This returns true if the first conditional is true when # the second conditional is true. sub conditional_true_when { my ($cond, $when) = @_; # Check the easy case first. if ($cond eq $when) { return 1; } # Check each component of $cond, which looks @COND1@@COND2@. foreach my $comp (split ('@', $cond)) { # The way we split will give null strings between each condition. next if ! $comp; if (index ($when, '@' . $comp . '@') == -1) { return 0; } } return 1; } # Check for an ambiguous conditional. This is called when a variable # or target is being defined conditionally. If we already know about # a definition that is true under the same conditions, then we have an # ambiguity. sub check_ambiguous_conditional { my ($var_name, $cond) = @_; my (@cond_vals) = split (' ', $conditional{$var_name}); while (@cond_vals) { my ($vcond) = shift (@cond_vals); shift (@cond_vals); if (conditional_true_when ($vcond, $cond) || conditional_true_when ($cond, $vcond)) { prt( "$var_name multiply defined in condition\n" ); } } } sub trim_line { my ($l) = shift; chomp $l; $l =~ s/\r$//; # and remove CR, if present $l =~ s/\t/ /g; # tab to space $l =~ s/\s\s/ /g while ($l =~ /\s\s/); # double space to single for ($l) { # trim leading and trailing spaces s/^\s+//; s/\s+$//; } return $l; } sub is_c_source { my ($f) = shift; if ( ($f =~ /\.c$/i) || ($f =~ /\.cpp$/i) || ($f =~ /\.cxx$/i) || ($f =~ /\.inl$/i) || ($f =~ /\.cc$/i) ) { return 1; } return 0; } sub is_h_special { my ($f) = shift; if (($f =~ /osg/i)||($f =~ /OpenThreads/i)||($f =~ /Producer/i)) { return 1; } return 0; } sub is_h_source { my ($f) = shift; if ( ($f =~ /\.h$/i) || ($f =~ /\.hpp$/i) || ($f =~ /\.hxx$/i) ) { return 1; } return 0; } sub is_dsw_file { my ($f) = shift; if ( ($f =~ /\.dsw$/i) || ($f =~ /\.dsp$/i) ) { return 1; } return 0; } sub is_sln_file { my ($f) = shift; if ( ($f =~ /\.sln$/i) || ($f =~ /\.vcproj$/i) ) { return 1; } return 0; } sub is_ch_source { my ($f) = shift; if (is_c_source($f) || is_h_source($f)) { return 1; } return 0; } sub is_my_type { my ($f) = shift; if (is_c_source($f)) { return $TYPE_C; } elsif (is_h_source($f)) { return $TYPE_H; } elsif (is_dsw_file($f)) { return $TYPE_DSW; } elsif (is_sln_file($f)) { return $TYPE_SLN; } elsif ($f =~ /^makefile\.am$/i) { return $TYPE_AM; } elsif ($f =~ /makefile/i) { return $TYPE_MAK; } return $TYPE_NONE; } sub mark_all_files { my ($f) = shift; my $lcf = lc($f); # 0 1 2 3 4 # push(@all_files, [$df, $ff, 0, $typ, $rd]) if ($typ); my $ac = scalar @all_files; for (my $i = 0; $i < $ac; $i++) { my $tf = lc($all_files[$i][1]); if ($tf eq $lcf) { my $ct = $all_files[$i][2]; $ct++; $all_files[$i][2] = $ct; return 1; } } return 0; } sub show_all_sources { my ($msg,$rd) = @_; my $ac = scalar @all_files; # push(@all_files, [$df, $ff, 0, $typ, $rd]) if ($typ); my ($mc, $i, $file, $line, $omsg); $mc = 0; my @files = (); my ($nam, $dir, $ext); # get count of MISSING items for ($i = 0; $i < $ac; $i++) { if ($all_files[$i][3] == $TYPE_C) { if ($all_files[$i][2] == 0) { $mc++; } } } if ($mc) { prt( "\nSources found, but MISSED - $mc ...root = $rd\n" ); for ($i = 0; $i < $ac; $i++) { if ($all_files[$i][3] == $TYPE_C) { if ($all_files[$i][2] == 0) { $file = $all_files[$i][1]; $omsg = " ".sub_common_folder($file, $rd)." "; $omsg = get_main_msg($file,sub_common_folder($file,$rd),1,"") if ($check4main2); # check if a main() prt( "$omsg\n" ); push(@files, $file) if ($recheck_am); } } } prt( "Above $mc Sources NOT INCLUDED in $msg ...\n\n" ); if ($recheck_am) { my @makes = get_all_makes(); $mc = 0; foreach my $mk (@makes) { if (open MK, "<$mk") { my @lines = <MK>; close MK; foreach $file (@files) { if ($check_full) { ($nam, $dir) = fileparse($file); foreach $line (@lines) { chomp $line; if ($line =~ /$nam/) { prt( "Note: [$nam] is in [$mk] ... line[$line]\n" ); $mc++; last; } } } else { ($nam, $dir, $ext) = fileparse( $file, qr/\.[^.]*/ ); foreach $line (@lines) { chomp $line; if ($line =~ /$nam/) { prt( "Note: [$nam] is in [$mk] ... line[$line]\n" ); $mc++; last; } } } } } } if ($mc) { prt( "Above $mc references should be checked ...\n\n" ); } } } } sub get_missed_makes { my ($rd) = shift; my $ac = scalar @all_files; my $i = 0; my @mam = (); for ($i = 0; $i < $ac; $i++) { if ($all_files[$i][3] == $TYPE_AM) { if ($all_files[$i][2] == 0) { my $file = $all_files[$i][1]; # get FULL (qualified) path name my ($nm, $path) = fileparse($file); # split it to name,path #my $rp = unix_2_dos(get_relative_path( $path, $rd ).$nm); my $rp = unix_2_dos(get_relative_path_2( $path, $rd ).$nm); push( @mam, $rp ); # pass back the DOS relative makefile.am entry } } } return @mam; } sub get_all_makes { my $ac = scalar @all_files; my $i = 0; my @mam = (); for ($i = 0; $i < $ac; $i++) { if ($all_files[$i][3] == $TYPE_AM) { my $file = $all_files[$i][1]; # get FULL (qualified) path name ###my ($nm, $path) = fileparse($file); # split it to name,path push( @mam, $file ); # pass back makefile.am full path } } return @mam; } ######################################################################## ####### ONLY DSP STUFF sub expand_here { local $_ = shift; s/\%cflags\%/$msvc_cflags/g; s/\%libs\%/$msvc_libs/g; s/\%dlibs\%/$msvc_dlibs/g; s/\%rlibs\%/$msvc_rlibs/g; return $_; } sub console_app_dsp_init { my ($name, $dsp_name) = @_; prt( "Creating console app type $dsp_name ...\n" ); my $ren = rename_2_old_bak( $dsp_name ); if ($ren) { prt( "Renamed original to ".(($ren == 1) ? "OLD" : "BAK")." ...\n" ); } open(DSP, ">$dsp_name") || mydie( "ERROR: Can't create $dsp_name: $!\n" ); print DSP expand_here(<<EOF); # Microsoft Developer Studio Project File - Name="$name" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=$name - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "$name.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "$name.mak" CFG="$name - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "$name - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "$name - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "\$(CFG)" == "$name - Win32 Release" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD CPP /nologo /W3 /GR /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /c %cflags% # SUBTRACT CPP /YX # ADD RSC /l 0xc09 /d "NDEBUG" BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 %libs% %rlibs% !ELSEIF "\$(CFG)" == "$name - Win32 Debug" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c %cflags% # ADD RSC /l 0xc09 /d "_DEBUG" BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD LINK32 kernel32.lib user32.lib winspool.lib comdlg32.lib gdi32.lib shell32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept %libs% %dlibs% !ENDIF # Begin Target # Name "$name - Win32 Release" # Name "$name - Win32 Debug" EOF close(DSP); } sub static_lib_dsp_init { my ($name, $dsp_name) = @_; prt( "Creating static library type $dsp_name ... \n" ); my $ren = rename_2_old_bak( $dsp_name ); if ($ren) { prt( "Renamed original to ".(($ren == 1) ? "OLD" : "BAK")." ...\n" ); } open(DSP, ">$dsp_name") || mydie( "ERROR: Can't create $dsp_name: $!\n" ); print DSP expand_here(<<EOF); # Microsoft Developer Studio Project File - Name="$name" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Static Library" 0x0104 CFG=$name - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "$name.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "$name.mak" CFG="$name - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "$name - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "$name - Win32 Debug" (based on "Win32 (x86) Static Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "\$(CFG)" == "$name - Win32 Release" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD CPP /nologo /W3 /GR /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /FD /c %cflags% # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo !ELSEIF "\$(CFG)" == "$name - Win32 Debug" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /FD /GZ /c %cflags% # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo !ENDIF # Begin Target # Name "$name - Win32 Release" # Name "$name - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc" EOF close(DSP); } sub end_dsp_file { my ($fil) = shift; if (open DSP, ">>$fil") { print DSP "# End Group\n"; # just the HEADER files - SHOULD ACCUMULATE THEM FOR HERE print DSP "# Begin Group \"Header Files\"\n"; print DSP "\n"; print DSP "# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n"; # 2009-06-09 Add HEADERS if nay found if (defined $am_headers{$last_project}) { my $lsrcs = $am_headers{$last_project}; my @arr = split(/\|/ , $lsrcs); # Sources foreach my $s (@arr) { $s = fix_rel($s); print DSP "# Begin Source File\n"; print DSP "\n"; print DSP "SOURCE=$s\n"; print DSP "# End Source File\n"; } } else { print DSP "\n"; } print DSP "# End Group\n"; print DSP "# End Target\n"; print DSP "# End Project\n"; close(DSP); prt( "[dbg30] Ending last DSP - [$fil] ...\n" ) if ($dbg30); } } sub get_am_incs { my ($prj) = shift; my $incs = ''; my $ics = ''; my @pths = (); my $ic = ''; if (defined $am_includes{$prj}) { $ics = $am_includes{$prj}; @pths = split(' ',$ics); foreach $ic (@pths) { $incs .= " " if (length($incs)); $incs .= "/I \"$ic\""; # could go for RELATIVE DIRECTORY } } if (defined $am_cppflags{$prj}) { $ics = $am_cppflags{$prj}; @pths = split(' ',$ics); foreach $ic (@pths) { $incs .= " " if (length($incs)); $incs .= "/D \"$ic\""; } } # 2009-05-09 - ensure _CRT_SECURE_NO_DEPRECATE is added if ($add_CRT_SECURE_NO_DEPRECATE) { if ( !($incs =~ /_CRT_SECURE_NO_DEPRECATE/) ) { $incs .= " " if !($incs =~ /\s$/); $incs .= "/D \"_CRT_SECURE_NO_DEPRECATE\""; } } if ($add_CONFIG_H) { if ( !($incs =~ /HAVE_CONFIG_H/) ) { $incs .= " " if !($incs =~ /\s$/); $incs .= "/D \"HAVE_CONFIG_H\""; } } if ($add_NOMINMAX) { if ( !($incs =~ /NOMINMAX/) ) { $incs .= " " if !($incs =~ /\s$/); $incs .= "/D \"NOMINMAX\""; } } return $incs; } sub get_am_libs { my ($prj) = shift; my $incs = ''; if (defined $am_libadds{$prj}) { $incs = $am_libadds{$prj}; } return $incs; } # write DSP file sub out_dsp_file { my ($prj, $fil, $src, $rd, $typ) = @_; my ($dsptype, $srcdir, $shtfil); if ($prj ne $last_project) { end_dsp_file($last_dsp_file) if (length($last_dsp_file)); $last_project = $prj; $last_dsp_file = $fil; $msvc_cflags = get_am_incs( $prj ); $msvc_libs = get_am_libs( $prj ); if ($typ) { static_lib_dsp_init( $prj, $fil ); $dsptype = 'static lib'; } else { console_app_dsp_init( $prj, $fil ); $dsptype = 'console app'; } $shtfil = subract_target_dir($fil); prtd( "Started new DSP $shtfil, project $prj, type $dsptype ...\n" ); } if (open OF, ">>$fil") { print OF "# Begin Source File\n"; print OF "\n"; $srcdir = $src; #if ($add_SOURCE_REL && length($src_relative)) { # $srcdir = $src_relative; # $srcdir .= "\\" if (! (($srcdir =~ /(\\|\/)$/) || ($src =~ /^(\\|\/)/)) ); # $srcdir .= "$src"; #} print OF "SOURCE=$srcdir\n"; print OF "# End Source File\n"; close OF; } } # RENAME A FILE TO .OLD, or .BAK # 0 - do nothing if file does not exist. # 1 - rename to .OLD if .OLD does NOT exist # 2 - rename to .BAK, if .OLD already exists, # 3 - deleting any previous .BAK ... sub rename_2_old_bak { my ($fil) = shift; my $ret = 0; if ( -f $fil ) { my ($nm,$dir,$ext) = fileparse( $fil, qr/\.[^.]*/ ); my $nmbo = $dir . $nm . '.old'; $ret = 1; if ( -f $nmbo) { $ret = 2; $nmbo = $dir . $nm . '.bak'; if ( -f $nmbo ) { $ret = 3; unlink $nmbo; } } rename $fil, $nmbo; } return $ret; } sub C_comment_starts { my ($txt) = shift; my $len = length($txt); my $ptxt = ''; my $ttxt = ''; my ($k, $ch, $pch, $k2, $nch); for ($k = 0; $k < $len; $k++) { $k2 = $k + 1; $ch = substr($txt,$k,1); $nch = (($k2 < $len) ? substr($txt,$k2,1) : ''); if (($ch eq '/')&&($nch eq '*')) { $ttxt = substr($txt,($k2+1)); return $k2, $ptxt, $ttxt; # return offset, previous and begin comment } $pch = $ch; $ptxt .= $ch; } return 0, $ptxt, $ttxt; } sub inline_comment_starts { my ($txt) = shift; my $len = length($txt); my $ptxt = ''; my ($k, $ch, $pch, $k2, $nch); for ($k = 0; $k < $len; $k++) { $k2 = $k + 1; $ch = substr($txt,$k,1); $nch = (($k2 < $len) ? substr($txt,$k2,1) : ''); if (($ch eq '/')&&($nch eq '/')) { return $k2, $ptxt; # return offset, previous } $pch = $ch; $ptxt .= $ch; } return 0, $ptxt; } sub C_comment_ends { my ($txt) = shift; my $len = length($txt); my $ttxt = ''; my ($k, $ch, $pch, $k2, $nch); for ($k = 0; $k < $len; $k++) { $k2 = $k + 1; $ch = substr($txt,$k,1); $nch = (($k2 < $len) ? substr($txt,$k2,1) : ''); if (($ch eq '*')&&($nch eq '/')) { $ttxt = substr($txt,($k2+1)); return $k2, $ttxt; # return trailing } $pch = $ch; } return 0, $ttxt; } sub get_C_file_lines { my ($inf) = shift; my (@lines, $lncnt, $line, $tline); my ($isc, $ptxt, $i, $ttxt, $ise, $atxt, $i2, $ctxt); my $incomm = 0; my $lnnum = 0; my ($typ, $inmacro, $len, $ch, $j, $braces, $pbrac); my ($msg); my @nlines = (); $inmacro = 0; $braces = 0; $pbrac = 0; if (open INF, "<$inf") { @lines = <INF>; close INF; $lncnt = scalar @lines; prt( "Processing $lncnt lines, from $inf ...\n") if ($dbg_comm); for ($i = 0; $i < $lncnt; $i++) { $lnnum++; $line = $lines[$i]; $tline = trim_all($line); if ( $incomm ) { ($ise,$atxt) = C_comment_ends($tline); if ($ise) { $msg = "$lnnum: Comment ends"; $msg .= " [$atxt] follows" if length($atxt); prt( "$msg\n" ) if ($dbg_comm); $incomm = 0; $tline = trim_all($atxt); } } if ( ! $incomm ) { $ctxt = $tline; ($isc,$ptxt,$ttxt) = C_comment_starts($tline); if ($isc) { # deal with any $ptxt .. ($ise,$atxt) = C_comment_ends($ttxt); if ($ise) { while ($isc && $ise) { $ptxt = trim_all($ptxt); $atxt = trim_all($atxt); $ctxt = $ptxt; $ctxt .= ' ' if (length($ctxt) && length($atxt) && ($atxt ne ';')); $ctxt .= $atxt if length($atxt); $ctxt = trim_all($ctxt); $msg = "$lnnum: Comment starts/ends - "; $msg .= "[$ptxt] before " if length($ptxt); $msg .= "[$atxt] follows " if length($atxt); prt( "$msg\n" ) if ($dbg_comm); ($isc,$ptxt,$ttxt) = C_comment_starts($ctxt); $atxt = ''; if ($isc) { ($ise,$atxt) = C_comment_ends($ttxt); } $ptxt = trim_all($ptxt); $atxt = trim_all($atxt); $ctxt = $ptxt; $ctxt .= ' ' if (length($ctxt) && length($atxt) && ($atxt ne ';')); ###$ctxt .= ' ' if length($ctxt); $ctxt .= $atxt if length($atxt); $ctxt = trim_all($ctxt); } } else { $ctxt = trim_all($ptxt); $msg = "$lnnum: IN Comment"; $msg .= " after [$ptxt]" if length($ptxt); prt( "$msg\n" ) if ($dbg_comm); $incomm = 1; } } $tline = $ctxt; if (! $incomm) { ($isc,$ptxt) = inline_comment_starts($tline); if ($isc) { $ctxt = trim_all($ptxt); $msg = "$lnnum: INLINE Comment"; $msg .= " after [$ptxt]" if length($ptxt); prt( "$msg\n" ) if ($dbg_comm); } else { $ctxt = $tline; } } } $tline = trim_all($ctxt); push(@nlines, $tline) if length($tline); } } else { prtw( "WARNING: Unable to OPEN [$inf]!\n" ); } return @nlines; } sub get_include_list { my ($fil, $rarr) = @_; my @lines = (); if ( -f $fil ) { my @lines = get_C_file_lines($fil); my $lncnt = scalar @lines; my $inc = ''; prt( "Processing $lncnt lines, from $fil ...\n") if ($dbg_incs); for (my $i = 0; $i < $lncnt; $i++) { my $line = $lines[$i]; if ($line =~ /\s*#\s*include\s+(.+)/ ) { $inc = $1; push(@{$rarr},$inc); prt( "include: [$inc] ($line)\n" ) if ($dbg_incs); } } } else { prtw( "WARNING: Unable to find [$fil]!\n" ); } } sub show_inc_hash { my ($key, $val, $cnt); $cnt = scalar keys(%inc_hash); prt( "\nShow of $cnt keys in inc_hash ...\n" ); foreach $key (sort keys %inc_hash) { $val = $inc_hash{$key}; prt( "$key = [$val]\n" ); } prt("Done\n"); } # eof - amsrcs02.pl