Generated: Sun Aug 21 11:10:36 2011 from amsrcs03.pl 2010/09/22 170.3 KB.
# ########################################################################################### # NAME: amsrcs03.pl # AIM: MAKE DSP FILES - Given a folder, trace the makefile.am files, collecting # libraries, applications and sources. The process starts with scanning configure.ac (or .in) # 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 # ================================ # 22/09/2010 - Suspended in favour of amsrcs04.pl # 08/09/2010 - Another MASSIVE review - many, MANY CHANGES, including support for Makefile.in, # when there is NO Makefile.am, immediate exit if no configure.ac found, many more user options, etc # struggling between source directories - choose to suspend enhancement of this script # and start a new amsrcs04.pl, done completely different! # 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 perhaps 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/\.[^.]*/ ); use File::Spec; # File::Spec->rel2abs($rel); # we are IN the SLN directory, get ABSOLUTE from RELATIVE use Cwd; my $perl_dir = 'C:\GTools\perl'; unshift(@INC, $perl_dir); require 'fgutils02.pl' or die "Unable to load fgutils02.pl ...\n"; require '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 =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $perl_dir."\\temp.$pgmname.txt"; open_log($outfile); my $pack = $pgmname; # Options my $use_current_dir = 1; # if NOT input directory given, use current my $show_all_sources = 0; my $show_missed_sources = 0; my $load_log = 0; # load logfile into notepad at end my $support_makefile_in = 0; my $only_dry_run = 0; my $exit_bogus_macro = 0; my $main_root_dir = ''; my $target_dir = ''; # features my $abort_on_ac_config = 0; # we do NOT care about this 'mistake' ;=)) my $error_comment_saw_bk = 0; # am_line_error ($aln, "comment following trailing backslash") if $saw_bk; my $abort_on_conditional = 0; # complicated issue unresolved, but continuing anyway... 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 $min_line = 60; 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 $add_rel_src = 1; # add the relative source to output my $temp_in_file = ''; # $perl_dir."\\tempmfin.txt"; my $temp_in_macs = ''; # $perl_dir."\\tempinmac.txt"; my $write_temp_ds = 1; # this is MEANT to be ON, and the following BAT do the COPY job my $temp_upd_bat = $perl_dir."\\tempupd3.bat"; ############################### ####### 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]*(.*)\$"; # In *.in files, can find '@ON_WINDOWS@LINK = $(CC) $(LDFLAGS) -I. -I$(top_srcdir) -L.libs' 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]*([^)]+)"; my %ac_macro_skip = ( 'AC_CHECK_HEADERS' => 1, 'AC_CHECK_HEADER' => 2, 'AC_HELP_STRING' => 3, 'AC_DEFUN' => 4, 'AC_EGREP_CPP' => 5, 'AC_CHECK_FUNC' => 6, 'PKG_CHECK_MODULES' => 7, 'AC_CHECK_LIB' => 8, 'AC_ARG_ENABLE' => 9, 'AC_ARG_WITH' => 10 ); #### 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 $cmd_line = ''; 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 @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 ($full_fil_path); my @dspprojs = (); # list of PROJECTS created my @inf = (); my @other_inputs = (); # if (is_c_source($f)) { my $tot_c_sources = 0; # return $TYPE_C; # } elsif (is_h_source($f)) { my $tot_h_sources = 0; # return $TYPE_H; # } elsif (is_dsw_file($f)) { my $tot_dsw_sources = 0; # return $TYPE_DSW; # } elsif (is_sln_file($f)) { my $tot_sln_sources = 0; # return $TYPE_SLN; # } elsif ($f =~ /^Makefile\.(am|in)$/i) { my $tot_am_files = 0; # return $TYPE_AM; # } elsif ($f =~ /makefile/i) { my $tot_mk_files = 0; # return $TYPE_MAK; my $tot_others = 0; # return $TYPE_NONE; my %missed_exts = (); my ($c_cnt,$t_cnt,$h_cnt,$o_cnt,$p_cnt); my $act_am_ext = ''; # need to deal with Makefile.in slightly differently to get sources my $act_am_file = ''; my $act_am_dir = ''; my %discarded = (); my $act_rel_directory = ''; my @copy_bat = (); # set of COPIES to be done, via a BATCH file my $final_message = ''; my %incompete_macs = (); my %undefined_macs = (); my %content_by_file = (); # warnings my @warnings = (); my %warned_items = (); my $show_all_warns = 0; # show ALL warnings as they happen... my $cwd = cwd(); my $os = $^O; my %IN_MACS = ( 'BUILD_EXEEXT' => 'exe', 'BUILD_OBJEXT' => 'obj', 'CC' => 'cl', 'CC_FOR_BUILD' => 'cl', 'CFLAGS' => '', 'CFLAGS_FOR_BUILD' => '', 'CXX' => 'cl', 'CXXFLAGS' => '', 'CXXFLAGS_FOR_BUILD' => '', 'CXXLDFLAGS' => '', 'CXX_FOR_BUILD' => '', 'EBCDIC' => '', 'EXEEXT' => 'exe', 'HAVE_CPP' => '', 'INSTALL' => '', 'INSTALL_DATA' => '', 'LDFLAGS' => '', 'LIBTOOL' => 'link', 'LINK_SIZE' => '', 'MATCH_LIMIT' => '', 'MATCH_LIMIT_RECURSION' => '', 'MAYBE_CPP_TARGETS' => '', 'NEWLINE' => '', 'NOT_ON_WINDOWS' => '', 'NO_RECURSE' => 'no', 'OBJEXT' => 'obj', 'ON_WINDOWS' => '', 'PCRE_CPPLIB_VERSION' => '', 'PCRE_LIB_VERSION' => '', 'PCRE_POSIXLIB_VERSION' => '', 'POSIX_LIB' => '', 'POSIX_LOBJ' => '', 'POSIX_MALLOC_THRESHOLD' => '', 'POSIX_OBJ' => '', 'SHELL' => 'sh', 'UCP' => '', 'UTF8' => '', 'WIN_PREFIX' => '', 'bindir' => '', 'exec_prefix' => '', 'includedir' => '$(includedir)', 'libdir' => '', 'mandir' => '', 'prefix' => '', 'top_srcdir' => '$(top_srcdir)' ); ####################### # debug - should be ALL OFF for release my $debug_on = 0; my $def_in_dir = 'C:\Projects\Jack'; my $dbg01 = 0; # show EACH configure.ac line my $dbg02 = 0; # show "Storing configure_cond key $1 ... value=? ..." my $dbg03 = 0; # show "Substute $key=$nval ... setting $var_hash{$key} = $nval; my $dbg04 = 0; # show "Got ac_output_line = [$ac_output_line] ... my $dbg05 = 0; # show "Adding $input [$ff] to make_input_list ... my $dbg06 = 0; # list Makefile list found my $dbg07 = 0; # show each 'makefile' processed ... my $dbg08 = 0; # show "Group set to [$group] ... *AND* "Expanding variable $varname ... my $dbg09 = 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 = 0; # 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 = 0; # show "\nProcessing [$am_file] from input_files array ... my $dbg21 = 0; # show "Project: [$proj] - sources [$srcs] ... my $dbg22 = 0; # NOT PRESENTLY USED 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 = 0; # show "For $group, saved INCLUDES [$incs] my $dbg27 = 0; # show checking for substitution macros ... my $dbg28 = 0; # 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 $dbg31 = 0; # show if (/$AM_CONDITIONAL_PATTERN/o) { prt( "$aclnnum: [$acline]\n" ) if ($dbg31); my $dbg32 = 0; # show "MACRO [$key]=[$nval] my $dbg33 = 0; # show "Group set to [$group] ... my $dbg34 = 0; # out warning that avoided re-read of *ac file my $dbg35 = 0; # trace EACH if statement in read_am_file my $dbg36 = 0; # show uncased lines, assume to be 'rule continuation' in makefile.[am|in] scan my $dbg37 = 0; # show shell actions, in macro substitution my $dbg38 = 0; # prt(" [dbg38] $key = [$nval], changed from [$cline]\n") if ($dbg38); and more... my $dbg39 = 0; # For Makefile.in, show target separations... noisy... my $dbg40 = 0; # Show project source lists... my $dbg41 = 0; # prt("[dbg41] add_2_new_source_list: [$line] grp=[$grp], rel=[$sfil]\n") if ($dbg41); my $dbg42 = 0; # prtw( "WARNING:others:[dbg42] [$sf] [$s] ALREADY IN inc_hash!\n" ) if ($dbg42); my $dbg43 = 0; # show sifting of comments out of file lines my $dbg44 = 0; # show sifting of 'include' out of file lines my $dbg45 = 0; # prtw("WARNING:[dbg45] Using a LOOSE search, since [$proj] nor [$proj2]_SOURCES NOT FOUNT!\n") if ($dbg45); my $dbg46 = 0; # prt("[dbg46] Added to contents:1: [$value]\n") if ($dbg46); my $dbg47 = 0; # if ($dgb47) { foreach $input (@make_input_list) { prt $input = [$make_list{$input}] my $dbg48 = 0; # debug sub try_for_substitution($$$$) { ... } # 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($$); # FUNCTIONS # ===================================================== # debug my $dbg_base = 'dbg'; sub set_dbg_base($) { $dbg_base = shift; } sub get_dbg_var($) { my $val = shift; my $var = $dbg_base; my $res = -1; if ($val < 10) { $var .= "0$val"; } else { $var .= "$val"; } # from : http://perldoc.perl.org/functions/eval.html if (eval "defined \$$var") { $res = eval "\$$var"; } return $res; } sub get_dbg_stg() { my $s = ''; my ($i,$res,$i2); for ($i = 1; ;$i++) { $res = get_dbg_var($i); last if ($res == -1); if ($i < 10) { $i2 = "0$i"; } else { $i2 = "$i"; } if ($res) { $s .= "$i2 "; } } return $s; } sub get_dbg_range() { my ($i,$res); for ($i = 1; ;$i++) { $res = get_dbg_var($i); last if ($res == -1); } return $i - 1; } sub set_dbg_var($) { my $val = shift; my $var = $dbg_base; if ($val < 10) { $var .= "0$val"; } else { $var .= "$val"; } # from : http://perldoc.perl.org/functions/eval.html # NOT $$var++; # does not work! if (eval "defined \$$var") { eval "\$$var++"; } else { #print "ERROR: \$$var does NOT exist\n"; return 0; } return 1; } sub clear_dbg_var($) { my $val = shift; my $var = $dbg_base; if ($val < 10) { $var .= "0$val"; } else { $var .= "$val"; } # from : http://perldoc.perl.org/functions/eval.html # NOT $$var++; # does not work! if (eval "defined \$$var") { eval "\$$var = 0"; } else { #print "ERROR: \$$var does NOT exist\n"; return 0; } return 1; } sub set_all_dbg_on() { my ($i,$res); for ($i = 1; ;$i++) { $res = set_dbg_var($i); last if (!$res); } $show_all_warns = 1; # show ALL warnings as they happen... } sub set_all_dbg_off() { my ($i,$res); for ($i = 1; ;$i++) { $res = clear_dbg_var($i); last if (!$res); } $show_all_warns = 0; # show only NEW warnings... } ########################################################## # general sub repeat_dsp_info() { if (@dspinfo) { prt( "\nRepeat show of ".scalar @dspinfo." lines of DSP info ...\n" ); foreach my $di (@dspinfo) { prt("$di\n"); } } } sub prtw($) { my ($wm) = shift; prt($wm) if ($show_all_warns); # show ALL warnings as they happen... $wm =~ s/\n$//; if ( !defined $warned_items{$wm} ) { # but only KEEP if NOT a duplicate push(@warnings,$wm); $warned_items{$wm} = 1; prt("$wm\n") if (!$show_all_warns); # show ONLY NEW warnings... } } 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 ($val); } prt("Commands: [$cmd_line]\n"); if (length($msg)) { $msg .= "\n" if (! ($msg =~ /\n$/) ); prt($msg); } $msg = get_dbg_stg(); prt( "Debug ON: $msg\n" ) if (length($msg)); repeat_dsp_info(); # show the DSP/DSW files written - the whole purpose ;=)) prt($final_message) if (length($final_message)); 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 subract_source_dir($) { my ($fil) = shift; my $td = $act_rel_directory; 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 does_next_am_file_exist($) { my $fil = shift; return 1 if (-f $fil); return 1 if (-f $fil.'.am'); return 1 if ($support_makefile_in && (-f $fil.'.in')); return 1 if (-f $main_root_dir.$fil.'.am'); return 1 if ($support_makefile_in && (-f $main_root_dir.$fil.'.in')); return 0; } sub get_next_am_file($$) { my ($fil,$caller) = @_; return $fil if (-f $fil); return $fil if (-f $fil.'.am'); return $fil if ($support_makefile_in && (-f $fil.'.in')); return $fil if (-f $main_root_dir.$fil.'.am'); return $fil if ($support_makefile_in && (-f $main_root_dir.$fil.'.in')); if ($support_makefile_in) { pgm_exit(1,"ERROR:gnf:$caller: [$fil], nor [.am], NOR [.in] DOES NOT EXIST! WHY ARE WE HERE!\n"); } else { pgm_exit(1,"ERROR:gnf:$caller: [$fil], nor [.am] DOES NOT EXIST! WHY ARE WE HERE!\n"); } } sub get_next_full_am_file($) { my $fil = shift; my $nfil = $fil; if (-f $main_root_dir.$fil.'.am') { $nfil = $main_root_dir.$fil.'.am'; } elsif ($support_makefile_in && (-f $main_root_dir.$fil.'.in')) { $nfil = $main_root_dir.$fil.'.in'; } elsif (-f $fil.'.am') { $nfil = $fil.'.am'; } elsif ($support_makefile_in && (-f $fil.'.in')) { $nfil = $fil.'.in' ; } elsif (-f $fil) { $nfil = $fil; # already GOT name } else { if ($support_makefile_in) { pgm_exit(1,"ERROR:gnff: [$fil], nor [.am], NOR [.in] DOES NOT EXIST! WHY ARE WE HERE!\n"); } else { pgm_exit(1,"ERROR:gnff: [$fil], nor [.am] DOES NOT EXIST! WHY ARE WE HERE!\n"); } } return path_u2d($nfil); # always return the DOS form } sub is_if_else_endif($) { my ($txt) = shift; $txt = trim_all($txt); return 1 if ($txt =~ $IF_PATTERN); # = "^if[ \t]+\([A-Za-z][A-Za-z0-9_]*\)[ \t]*\(#.*\)?\$"; return 1 if ($txt =~ $ELSE_PATTERN); # = "^else[ \t]*\(#.*\)?\$"; return 1 if ($txt =~ $ENDIF_PATTERN); # = "^endif[ \t]*\(#.*\)?\$"; return 2 if ($txt =~ /^if\s+/); return 2 if ($txt =~ /^elif\s+/); return 2 if ($txt =~ /^else\s*/); return 2 if ($txt =~ /^endif\s*/); return 3 if ($txt =~ /^test\s+/); return 4 if ($txt =~ /^echo\s+/); return 0; } sub get_my_type_stg($) { my $typ = shift; if ($typ == $TYPE_C) { return "C/C++"; } elsif ($typ == $TYPE_H) { return "Headr"; } elsif ($typ == $TYPE_DSW) { return "Dsw/p"; } elsif ($typ == $TYPE_SLN) { return "VCSln"; } elsif ($typ == $TYPE_AM) { # /^Makefile\.(am|in)$/i) return "Mk_AM"; # $tot_am_files = 0; # return $TYPE_AM; } elsif ($typ == $TYPE_MAK) { # $f =~ /makefile/i) return "MakeF"; } return "NoGrp"; # my $tot_others = 0; # return $TYPE_NONE; } 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 local_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 local_is_h_special { my ($f) = shift; if (($f =~ /osg/i)||($f =~ /OpenThreads/i)||($f =~ /Producer/i)) { return 1; } return 0; } sub local_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)) { $tot_c_sources++; return $TYPE_C; } elsif (is_h_source($f)) { $tot_h_sources++; return $TYPE_H; } elsif (is_dsw_file($f)) { $tot_dsw_sources++; return $TYPE_DSW; } elsif (is_sln_file($f)) { $tot_sln_sources++; return $TYPE_SLN; } elsif ($f =~ /^Makefile\.(am|in)$/i) { $tot_am_files++; return $TYPE_AM; } elsif ($f =~ /makefile/i) { $tot_mk_files++; return $TYPE_MAK; } $tot_others++; my ($nm, $dr, $fe) = fileparse( $f, qr/\.[^.]*/ ); if (defined $missed_exts{$fe}) { $missed_exts{$fe}++; } else { $missed_exts{$fe} = 1; } return $TYPE_NONE; } sub get_top_files($$) { my ($td,$lev) = @_; my @dirs = (); my ($ff,$df,@dfiles,$typ,$nam,$dir,$rd); $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 prt("Moment, getting full file list of $td...\n" ) if ($lev == 0); if (opendir(DIR, $td)) { @dfiles = readdir(DIR); close DIR; foreach $df (@dfiles) { next if (($df eq '.') || ($df eq '..')); $ff = $td.$df; if (-f $ff) { $typ = is_my_type($df); ($nam,$dir) = fileparse($ff); #my $rd = get_relative_path( $dir, $td ); $rd = get_relative_path_2( $dir, $td ); ##my $rd = unix_2_dos($rp); # 0 1 2 3 4 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,($lev + 1)); } prt( "Got ".scalar @all_files." files ...\n" ) if ($lev == 0); } # fix relative directory - fix relative path - path fix # Remove any DOT or DOUBLE DOT from the PATH sub loc_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; my ($am_file,$mk); my ($fil_name, $fil_dir) = fileparse($afile); #$full_fil_path = unix_2_dos($main_root_dir . $fil_dir); $full_fil_path = loc_fix_rel($main_root_dir . $fil_dir); # also returns DOS, minus trailing '\' $full_fil_path .= "\\" if ( !($full_fil_path =~ /\\$/) ); # add trailing '\' IF none # 2010-08-26 - This does NOT account for Makefile.in!!! Soooo #$next_am_file = $afile; #$next_am_file .= ".am" if (has_no_extent($afile) && !is_am_file($afile)); $next_am_file = get_next_am_file($afile,"process_one_file"); prt( "\n[dbg20] Processing [$next_am_file] from input_files array ...\n" ) if ($dbg20); process_am_file($dsp_package, $afile, $main_root_dir) if !exclude_dir($afile); $am_file = get_next_full_am_file($afile); $mk = mark_all_files($am_file); prtw( "WARNING:1: NOT FOUND IN MARK [$am_file]!\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,$cnt); $cnt = scalar @{$rpacks}; if ($cnt == 0) { prtd( "Avoided creating $dsw_name, since NO packages to add!\n" ); return; } 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,$tmp_out,$dsp); $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 = path_u2d($out_file); $dsp = $out_file; # ONLY generate a TEMP DSW in the $perl_dir ########################################### if ($write_temp_ds) { $tmp_out = $perl_dir; $tmp_out .= "\\" if (length($tmp_out) && !($tmp_out =~ /(\\|\/)$/) ); if (length($dsp_package)) { $tmp_out .= 'temp.'.$dsp_package.'.dsw'; } else { $tmp_out .= 'temp_list.dsw'; } $tmp_out = path_u2d($tmp_out); push(@copy_bat,[$tmp_out,$out_file]); $out_file = $tmp_out; # switch to using TEMP FILE } if ($only_dry_run) { prtw("WARNING: Would write [$tmp_out], for [$dsp], but DRY RUN is ON\n"); } else { generate_dsw( $out_file, \@dspprojs, \%other_deps ); } } # ===================================================== ####################################################################### ##### 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]; # but it appears these are NOT target relative! NEED FIX *TBD* 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, $sf, $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 $sf (@arr) { $s = $sf; if (-f $sf) { $ff = $sf; } else { $ind = index($s, '$(top_srcdir)'); $s = substr($s, $ind + 14) if ($ind >= 0); $s = loc_fix_rel($s); $ff = $rd . $s; } @incs = (); get_include_list("giho", $sf, $ff, \@incs); if (defined $inc_hash{$s}) { prtw( "WARNING:others:[dbg42] [$sf] [$s] ALREADY IN inc_hash!\n" ) if ($dbg42); $inc_hash{$s} .= join(' ', @incs); } else { $inc_hash{$s} = join(' ', @incs); } } } } sub gen_inc_hash_am { my ($rd) = shift; my ($sf, $s, $ff, $mk, $om); my ($lsrcs, @arr); my @incs = (); foreach my $key (keys %am_projects) { $lsrcs = $am_projects{$key}; @arr = split(/\|/ , $lsrcs); # Sources foreach $sf (@arr) { $s = loc_fix_rel($sf); $ff = $rd . $s; @incs = (); get_include_list("giha", $sf, $ff, \@incs); if (defined $inc_hash{$s}) { prtw( "WARNING:am: [$sf] [$s] ALREADY IN inc_hash!\n" ) if ($dbg42); $inc_hash{$s} .= join(' ',@incs); } else { $inc_hash{$s} = join(' ',@incs); } } } } sub show_other_projects { my ($rd) = shift; my ($lsrcs, @arr, $s, $sf, $ind, $ff, $mk, $om); my ($in_file, $in_dir, $rel_src); my ($out_file,$tmp_out); $last_dsp_file = ''; prt( "\nFound $o_cnt OTHER projects ...root = $rd\n" ); foreach my $key (keys %other_projs) { $lsrcs = $other_projs{$key}; $out_file = $target_dir; $out_file .= "\\" if !($out_file =~ /(\\|\/)$/); $out_file .= $key.'.dsp'; $out_file = path_u2d($out_file); # ONLY GENERATE TEMPORARY DSP FILE in the $perl_dir if ($write_temp_ds) { $tmp_out = $perl_dir; $tmp_out .= "\\" if !($tmp_out =~ /(\\|\/)$/); $tmp_out .= 'temp.'.$key.'.dsp'; $tmp_out = path_u2d($tmp_out); push(@copy_bat,[$tmp_out,$out_file]); $out_file = $tmp_out; } push(@dspprojs, ".\\$key.dsp,$key"); @arr = split(/\*/, $lsrcs); # get sources SPLIT prt( "Project: $key\n" ); foreach $sf (@arr) { $s = $sf; $ind = index($s, '$(top_srcdir)'); $s = substr($s, $ind + 14) if ($ind >= 0); $s = loc_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 ); # pgm_exit(1,"Key $key: Source file [$sf] [$s] dir=[$in_dir] targ=[$target_dir] rel=[$rel_src] file[$in_file]\n"); $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 = "File:C: [$s] ff=[$ff] "; $om .= "(rs=$rel_src)" if ($add_rel_src); } $om .= "C SOURCE NOT FOUND IN MARK!" if (!$mk); prt("$om\n"); # generate DSP file out_dsp_file($key, $out_file, $rel_src, $rd, 0) if ($out_dsp2); } else { $om = "File: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)) { # this is also where HEADERS are added end_dsp_file($last_dsp_file) if ($out_dsp2); $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,$tmp_out); 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}; $out_file = $target_dir; $out_file .= "\\" if !($out_file =~ /(\\|\/)$/); $out_file .= $key.'.dsp'; $out_file = path_u2d($out_file); # ONLY GENERATE A TEMPORARY DSP FILE in the $perl_dir #$out_file = $outdir.$key.'.dsp'; #$out_file = 'temp.'.$key.'.dsp'; if ($write_temp_ds) { $tmp_out = $perl_dir; $tmp_out .= "\\" if !($tmp_out =~ /(\\|\/)$/); $tmp_out .= 'temp.'.$key.'.dsp'; $tmp_out = path_u2d($tmp_out); push(@copy_bat,[$tmp_out,$out_file]); $out_file = $tmp_out; } # and store the relative actual DSP file name, for DSW generation push(@dspprojs, ".\\$key.dsp,$key"); @arr = split(/\|/ , $lsrcs); # Sources prt( "Project: $key\n" ); foreach $s (@arr) { $s = loc_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 = "File: [$s] ff=[$ff] "; $om .= "(rs=$rel_src)" if ($add_rel_src); } if (!$mk) { $om .= " NOT FOUND in MARK!"; } prt("$om\n"); # generate TEMP DSP file out_dsp_file($key, $out_file, $rel_src, $rd, 1) if ($out_dsp); } } if ( length($last_dsp_file) ) { # this is also where HEADERS, if any, are ADDED to the DSP end_dsp_file($last_dsp_file) if ($out_dsp); $last_dsp_file = ''; $last_project = ''; } } sub get_main_msg { my ($ffn,$sfn,$no,$rs) = @_; my $fom = "file:C: [$sfn] ff=[$ffn] "; $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 test_root_folder($) { my $rd = shift; $rd .= "\\" if !($rd =~ /(\\|\/)$/); my $ff = path_u2d($rd.'configure.ac'); return 1 if (-f $ff); $ff = path_u2d($rd.'configure.in'); return 1 if (-f $ff); return 0; } sub scan_root_folder { my ($rd) = shift; $rd .= "\\" if !(substr($rd,-1,1) =~ /(\\|\/)/); my $ff = $rd; $ff .= 'configure.ac'; if (! -f $ff) { # try the ONLY altenative $ff = $rd.'configure.in'; if (! -f $ff) { pgm_exit(1,"ERROR: Can NOT locate configure.ac nor configure.in in [$rd]! Aborting!\n"); } } prt( "Scanning CONFIG file [$ff]...\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 ($dbg06) { 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" ); } pgm_exit(1,"ERROR: No 'makefiles' found in root folder scan!\n") if (!@input_files); } 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( "[dbg27] 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( "[dbg27] Found:do_macro_sub2: returning [$ritem] ...\n" ) if ($dbg27); return $ritem; } else { $undefined_macs{$item} = 1; prt( "[dbg27] NOT FOUND:do_macro_sub2: [$item] Added to undefined...\n" ) if ($dbg27); } return $item; } sub do_macro_sub { my ($item) = shift; if ($item =~ /^\$/) { my $msub = substr($item,1); # remove leading '$' $msub =~ s/^\{(.+)\}$/$1/; my $ritem = do_macro_sub2($msub); if ($ritem ne $msub) { return $ritem; } } return $item; } sub drop_trailing_dots($) { my $fil = shift; $fil = path_u2d($fil); my @arr = split(/\\/,$fil); my ($path); my $nfil = ''; foreach $path (@arr) { $path =~ s/\.$//; $nfil .= "\\" if (length($nfil)); $nfil .= $path; } return $nfil; } sub is_shell_action($) { my $txt = shift; return 1 if ($txt =~ /^`.+`$/); return 0; } # 2010-08-27: This could be split(/\s/,$line), but there is a # problem with name="with space", that this overcomes. # Slower. but sure the split is as desired. # This version obeys either type of quote - single or double sub local_space_split($) { my ($lin) = shift; my $ll = length($lin); my $tag = ''; my @rarr = (); my $inquots = 0; my ($p,$ch,$cq); for ($p = 0; $p < $ll; $p++) { $ch = substr($lin,$p,1); if ($inquots) { $tag .= $ch; if ($ch eq $cq) { $inquots = 0; } } else { if ($ch =~ /\s/) { push(@rarr, $tag) if (length($tag)); $tag = ''; } else { $tag .= $ch; if (($ch eq '"')||($ch eq "'")) { $inquots = 1; $cq = $ch } } } } push(@rarr, $tag) if (length($tag)); return @rarr; } sub local_strip_both_quotes($) { my $txt = shift; if ($txt =~ /^'(.+)'$/) { return $1; } if ($txt =~ /^"(.+)"$/) { return $1; } return $txt; } sub grep_for_value($$) { my ($file,$find) = @_; my $res = ''; if (open INF,"<$file") { my @lns = <INF>; close INF; my ($ln,$ind); foreach $ln (@lns) { $ind = index($ln,$find); if ($ind >= 0) { chomp $ln; $res = $ln; last; } } } else { prtw("WARNING: Unable to open file [$file]\n"); } return $res; } # cut range # N N'th byte, char or field, counted from 1 # N- from N'th to end # N-M from N'th to M'th (included) # -M from 1st to M'th (included) sub get_cut_range($$) { my ($txt,$rrng) = @_; if ($txt =~ /^\d+$/) { # only digits if ($txt >= 1) { ${$rrng}[0] = 1; ${$rrng}[1] = $txt; return 1; } } elsif ($txt =~ /^\d+-\d*$/) { my @arr = split('-',$txt); my ($bgn,$end,$len); $len = scalar @arr; if ($len == 1) { $bgn = $arr[0]; if ($bgn >= 1) { ${$rrng}[0] = $bgn; ${$rrng}[1] = -1; return 1; } } elsif ($len == 2) { $bgn = $arr[0]; $end = $arr[1]; if (($bgn >= 1)&&($end >= $bgn)) { ${$rrng}[0] = $bgn; ${$rrng}[1] = $end; } } } elsif ($txt =~ /^-/) { $txt = substr($txt,1); if ($txt =~ /^\d+$/) { ${$rrng}[0] = 1; ${$rrng}[1] = $txt; return 1; } } return 0; } sub set_by_shell_action($$$) { my ($dir,$key,$rval) = @_; my $val = ${$rval}; my (@arr,$len,$act,$k,$res,$find,$file,$rng,$oval,$rlen); $res = ''; $oval = $val; prt("Set by shell [$key] val [${$rval}], in dir [$dir]\n") if ($dbg37); if ($val =~ /^`(.+)`$/) { $val = $1; @arr = local_space_split($val); $len = scalar @arr; for ($k = 0; $k < $len; $k++) { $act = $arr[$k]; if ($act eq 'grep') { # ok expect 'something' in file if (($k + 2) < $len) { $k++; $find = strip_both_quotes($arr[$k]); $k++; $file = $arr[$k]; $file =~ s/\$\{srcdir\}/$dir/; $file = path_u2d($file); $file =~ s/\\\\/\\/g; prt("Act = $act, find [$find], in [$file]\n") if ($dbg37); $res = grep_for_value($file,$find); if (length($res)) { prt("Result: [$res]\n") if ($dbg37); } else { prtw("WARNING: grep_for_value: $act, find [$find], in [$file] in [$dir] FAILED!\n"); } } } elsif ($act eq 'cut') { # expect - like cut -c 29- $k++; if ($k < $len) { $find = $arr[$k]; $k++; if ($k < $len) { $file = $arr[$k]; prt("Act = $act, type [$find], range [$file]\n") if ($dbg37); $rlen = length($res); if ($rlen) { my (@rng); # cut range if (get_cut_range($file,\@rng)) { my ($bgn,$end,$dif); $bgn = $rng[0]; $end = $rng[1]; prt("Got 'cut' range [$bgn] to [".(($end == -1) ? "End" : $end)."], on string [$rlen]\n") if ($dbg37); if ($end == -1) { if (($bgn - 1) < $rlen) { $val = substr($res,($bgn - 1)); } else { $val = ''; } } else { $dif = $end - $bgn + 1; $bgn--; $val = substr($res,$bgn,$dif); } } } } } } elsif ($act eq '|') { prt("Act = $act\n") if ($dbg37); } } } if ($dbg37) { prt("Setting NEW value [$val]\n") if ($val ne $oval); } ${$rval} = $val; } sub get_sub_for($$) { my ($item,$rval) = @_; my ($nval); if (defined $config_ac_macros{$item}) { $nval = $config_ac_macros{$item}; if ( !($nval =~ /\$/) ) { ${$rval} = $nval; return 1; } } if (defined $IN_MACS{$item}) { $nval = $IN_MACS{$item}; if ( !($nval =~ /\$/) ) { ${$rval} = $nval; return 1; } } return 0; } # deal with messy things like sub do_mac_subs($$$$); # key [CXX_FOR_BUILD] val [${CXX_FOR_BUILD:-'$(CXX)'}] # key [MATCH_LIMIT_RECURSION] val [-DMATCH_LIMIT_RECURSION=$withval] # key [BUILD_EXEEXT] val [${BUILD_EXEEXT:-'$(EXEEXT)'}] # key [CFLAGS_FOR_BUILD] val [${CFLAGS_FOR_BUILD:-'$(CFLAGS)'}] # key [PCRE_VERSION] val [${PCRE_MAJOR}.${PCRE_MINOR}${PCRE_PRERELEASE}] # key [PCRE_MAJOR] val [`grep '#define PCRE_MAJOR' ${srcdir}/pcre.h | cut -c 29-`] sub do_mac_subs($$$$) { my ($dir,$key,$val,$lev) = @_; #prt("Mac Subs key [$key] val [$val], in dir [$dir]\n"); my ($sub,$nval,$mac); if (is_shell_action($val)) { set_by_shell_action($dir,$key,\$val); } elsif ($val =~ /\$/) { # probably some substitution required! $sub = $key.":-"; if ($val =~ /$sub/) { $val =~ s/$sub//; } # ${'$(CXXFLAGS)'} if ($val =~ /^\$\{'\$\((\w+)\)'\}$/) { $sub = $1; if (get_sub_for($sub,\$nval)) { $val = $nval; return $val; } } if ($val =~ /^\$\{(\w+):-(.+)\}$/) { $sub = "\${".$1; $mac = strip_both_quotes($2); $val =~ s/$sub//; $val =~ s/\}$//; if ($mac =~ /^\$\{'\$\((\w+)\)'\}$/) { $sub = $1; if (get_sub_for($sub,\$nval)) { $val = $nval; return $val; } } } # [${PCRE_MAJOR}.${PCRE_MINOR}${PCRE_PRERELEASE} while ($val =~ /\$\{(\w+)\}/) { $sub = $1; if (get_sub_for($sub,\$nval)) { prt(" [dbg38] Got SUB for [$val] item '\${$sub}' TO [$nval]\n") if ($dbg38); $val =~ s/\$\{$sub\}/$nval/; prt(" [dbg38] Value after the SUB [$val]\n") if ($dbg38); } else { prt(" [dbg38] FAILED to get SUB for [$val] [$sub]\n") if ($dbg38); last; } } } return $val; } # separate ${JACK_API_CURRENT}:${JACK_API_REVISION}:${JACK_API_AGE} # [dbg01] 109: [JACK_VERSION=$JACK_MAJOR_VERSION.$JACK_MINOR_VERSION.${JACK_MICRO_VERSION}${BETA}] sub macro_split($) { my ($txt) = @_; my @arr = (); my $len = length($txt); my ($i,$tag,$ch,,$nc,$mac,$k); $tag = ''; for ($i = 0; $i < $len; $i++) { $ch = substr($txt,$i,1); if ($ch eq '$') { $k = $i + 1; if ((($k+3) < $len)&&(substr($txt,$k,1) eq '{')) { $k++; $mac = '${'; for (; $k < $len; $k++) { $nc = substr($txt,$k,1); $mac .= $nc; last if ($nc eq '}'); last if !($nc =~ /\w/); } if ($nc eq '}') { push(@arr,$tag) if (length($tag)); $tag = ''; push(@arr,$mac); $ch = ''; $i = $k; } } elsif (($k+2) < $len) { $mac = '$'; # without {...} for (; $k < $len; $k++) { $nc = substr($txt,$k,1); last if !($nc =~ /\w/); # until NOT \w char, or string ended $mac .= $nc; # accumulate the macro } push(@arr,$tag) if (length($tag)); $tag = ''; push(@arr,$mac); $ch = ''; $i = $k; } } $tag .= $ch; } return @arr; } # like [dbg01] JACK_SO_VERSION=${JACK_API_CURRENT}:${JACK_API_REVISION}:${JACK_API_AGE} sub try_for_substitution($$$$) { my ($val,$lnn,$rh,$by) = @_; if ($val =~ /\$\{\w+\}/) { prt("[dbg48] $lnn: try_for_substitution: for [$val] in $by\n") if ($dbg48); my $oval = $val; my @arr = macro_split($val); my ($item,$key,$nval,$cnt); $cnt = 0; foreach $item (@arr) { $cnt++; next if ($item =~ /^\s+$/); prt("[dbg48] $lnn:$cnt: Checking [$item]\n") if ($dbg48); if ($item =~ /^\$\{(\w+)\}$/) { $key = $1; if (defined ${$rh}{$key}) { $nval = ${$rh}{$key}; if ($nval =~ /\$/) { prt("[dbg48] $lnn:$cnt: [$key] Can NOT replace a macro with another [$nval]\n") if ($dbg48); $incompete_macs{$key} = $by; } else { #$mac = '\\${'.$key.'}'; $val =~ s/\$\{$key\}/$nval/; prt("[dbg48] $lnn:$cnt: [$key] Doing sustitution [$key] TO [$nval]\n") if ($dbg48); } } else { $undefined_macs{$key} = $by; prt("[dbg48] $lnn:$cnt: Added key [$key] to undefined macros...\n") if ($dbg48); #$mac = '\\${'.$key.'}'; $val =~ s/\$\{$key\}//; prt("[dbg48] $lnn:$cnt: [$key] Doing sustitution [$key] TO [<blank>]\n") if ($dbg48); } } elsif ($item =~ /^\$(\w+)$/) { $key = $1; if (defined ${$rh}{$key}) { $nval = ${$rh}{$key}; if ($nval =~ /\$/) { prt("[dbg48] $lnn:$cnt: [$key] Can NOT replace a macro with another [$nval]\n") if ($dbg48); $incompete_macs{$key} = $by; } else { #$mac = '\\$'.$key; $val =~ s/\$$key/$nval/; prt("[dbg48] $lnn:$cnt: [$key] Doing sustitution [$key] TO [$nval]\n") if ($dbg48); } } else { $undefined_macs{$key} = $by; prt("[dbg48] $lnn:$cnt: Added key [$key] to undefined macros...\n") if ($dbg48); #$mac = '\\$'.$key; $val =~ s/\$$key//; prt("[dbg48] $lnn:$cnt: [$key] Doing sustitution [$key] TO [<blank>]\n") if ($dbg48); } } else { prt("[dbg48] $lnn:$cnt: No match of [$item]\n") if ($dbg48); } } if ($val ne $oval) { prt("[dbg48] $lnn:$cnt: Changed to [$val]\n") if ($dbg48); } } return $val; } sub eat_ac_macro($$$$) { my ($line,$max,$ri,$rlines) = @_; my $len = length($line); my ($i,$ch,$brcnt,$k,$k2,$lcnt,$acmac); # 1 - Eat the AC MACRO NAME $acmac = ''; $k = ${$ri}; for ($i = 0; $i < $len; $i++) { $ch = substr($line,$i,1); last if (!($ch =~ /\w/)); $acmac .= $ch; } if ($ch ne '(') { pgm_exit(1,"ERROR: mac=[$acmac] Fix eat_ac_macro to accept [$ch] following 'name'!\n"); } $i++; # essentially get to END of MACRO - may be mutiple lines $brcnt = 0; $lcnt = 1; for (; $i < $len; $i++) { $ch = substr($line,$i,1); if ($ch eq '(') { $brcnt++; } elsif ($ch eq ')') { if ($brcnt) { $brcnt--; } else { last; } } } if ($ch ne ')') { # oops, need more lines $k++; $k2 = $k + 1; # prt( "[dbg01] $k2: need more lines...($brcnt)\n" ) if ($dbg01); while ($k < $max) { $line = trim_all(${$rlines}[$k]); $lcnt++; $len = length($line); prt( "[dbg01] $k2: [$line] AC_MACRO cont...($brcnt) line $lcnt, len $len\n" ) if ($dbg01); for ($i = 0; $i < $len; $i++) { $ch = substr($line,$i,1); if ($ch eq '(') { #prt("Bumped brcnt [$brcnt]\n"); $brcnt++; } elsif ($ch eq ')') { if ($brcnt) { $brcnt--; $ch = ''; # CLEAR this char - is NOT the end #prt("Decrement brcnt [$brcnt]\n"); } else { #prt( "[dbg01] $k2: Multipline macro EXIT1...($brcnt) lines $lcnt\n" ) if ($dbg01); last; } } } if ($ch eq ')') { prt( "[dbg01] $k2: Multipline [$acmac] macro EXIT2... lines $lcnt\n\n" ) if ($dbg01); last; } $k++; # need MORE $k2 = $k + 1; } pgm_exit(1,"ERROR: Ran out of line in an ac macro!\n") if ($k >= $max); ${$ri} = $k; # pass back line number } } sub scan_one_configure_file { my ($filename, $rd) = @_; # $filename = path_u2d($filename); $filename = drop_trailing_dots($filename); if( is_in_ac_done($filename) ) { prtw("[dbg34] WARNING: Avoided repeated scan of [$filename]!\n") if ($dbg34); return; } if (! -f $filename) { pgm_exit(1,"ERROR: Can NOT find file [$filename]!\n" ); } if (! open CONFIGURE, "<$filename") { #prtw( "WARNING: can't open '$filename': $!\n" ); pgm_exit(1,"ERROR: can't open [$filename] Reason: $!\n" ); return; } my @lines = <CONFIGURE>; close CONFIGURE; push(@ac_scanned, $filename); prt("Processing configure file [$filename]...\n"); my ($ac_name,$ac_dir) = fileparse($filename); my $in_ac_output = 0; my $ac_output_line = ''; my ($ff,$fline,$cline,$acline); my $aclnum = 0; my %var_hash = (); my ($key,$nval); my ($local,$input,@rest); my ($one_hdr,$item,@arr); my $lncnt = scalar @lines; my ($i); for ($i = 0; $i < $lncnt; $i++) { $aclnum = $i + 1; $fline = $lines[$i]; $cline = $fline; # copy current file line chomp $cline; $acline = trim_all($cline); ###prt( "$cline\n" ); # Remove comments from current line. next if ($acline =~ /^dnl\s+/); next if ($acline =~ /^#/); next if (length($acline) == 0); prt( "[dbg01] $aclnum: [$cline]\n" ) if ($dbg01); if (($acline =~ /^(\w+)\(/) && (defined $ac_macro_skip{$1})) { eat_ac_macro($acline,$lncnt,\$i,\@lines); next; } #if ($cline =~ /^\s*(\w+)="(\d+)"$/) { if ($cline =~ /^\s*(\w+)="*(\d+)"*$/) { $key = $1; $nval = strip_both_quotes($2); prt("[dbg03|32] MACRO:N: [$key]=[$nval] line:$aclnum: [$acline]\n" ) if ($dbg32 || $dbg03); $var_hash{$key} = $nval; $config_ac_macros{$key} = $nval; ##} elsif ($cline =~ /^(\w+)="(.+)"$/) { ##} elsif ($cline =~ /^(\w+)="{0,1}(.+)"{0,1}$/) { ##} elsif ($cline =~ /^(\w+)=(.+)$/) { } elsif ($cline =~ /^\s*(\w+)=(.+)$/) { $key = $1; $nval = strip_both_quotes($2); #prt( "[dbg03] Sub [$key]=[$nval]\n" ) if ($dbg03); $nval = try_for_substitution($nval,$aclnum,\%config_ac_macros,"config_ac_macros"); prt("[dbg03|32] MACRO:S: [$key]=[$nval] line:$aclnum: [$acline]\n" ) if ($dbg32 || $dbg03); $var_hash{$key} = $nval; $config_ac_macros{$key} = $nval; } elsif ($cline =~ /^\s*(\w+)=\s*$/) { $key = $1; $nval = ''; prt("[dbg03|32] MACRO:B: [$key]=[$nval] line:$aclnum: [$acline]\n" ) if ($dbg32 || $dbg03); $var_hash{$key} = $nval; $config_ac_macros{$key} = $nval; } elsif ($cline =~ /=/) { if (is_if_else_endif($cline)) { # this CAN have a equal sign } else { prtw( "WARNING: '=' NOT handled! line:$aclnum: [$acline]\n" ); } } # Skip macro definitions. Otherwise we might be confused into # thinking that a macro that was only defined was actually # used. # Follow includes. This is a weirdness commonly in use at # Cygnus and hopefully nowhere else. if (($cline =~ /sinclude\((.*)\)/) && (-f ($rd.$1))) { $ff = $rd.$1; scan_one_configure_file ($ff, $rd); } if (!$in_ac_output && (($cline =~ s/AC_OUTPUT\s*\(\[?//) || ($cline =~ s/AC_CONFIG_FILES\s*\(\[?// ) ) ) { $in_ac_output = 1; $ac_output_line = $aclnum; # get LINE number prt( "[dbg4] Got ac_output_line = [$ac_output_line] ...\n" ) if ($dbg04); } if ($in_ac_output) { my $closing = 0; if ($cline =~ s/[\]\),].*$//) { $in_ac_output = 0; $closing = 1; } # Look at potential Makefile.am's @arr = split(/\s/,$cline); foreach $item (@arr) { # Must skip empty string for Perl 4. next if (($item eq "\\") || ($item eq '')); ($local,$input,@rest) = split(/:/,$item); if (!$input) { $input = $local; } else { $input =~ s/\.in$//; } $ff = $rd . $input . '.am'; if (-f $ff) { prt( "[dbg05] Adding $input [$ff] to make_input_list ...\n" ) if ($dbg05); push(@make_input_list, $input); $make_list{$input} = join(':', ($local,@rest)); } else { # try HARDER with 'Makefile' if ($input =~ /^Makefile$/) { $ff = $rd . $input . '.in'; if (-f $ff) { prt( "[dbg05] Adding $input [$ff] to make_input_list ...\n" ) if ($dbg05); push(@make_input_list, $input); $make_list{$input} = join(':', ($local,@rest)); next; } } prt( "[dbg05] Adding $input [$ff] to other_input_files ...\n" ) if ($dbg05); # We have a file that automake should cause to be # rebuilt, but shouldn't generate itself. push (@other_input_files, $item); } } } # Handle configuration headers. A config header of `[$1]' # means we are actually scanning AM_CONFIG_HEADER from # aclocal.m4. if (($cline =~ /A([CM])_CONFIG_HEADER\s*\((.*)\)/) && ($2 ne '[$1]')) { if (($1 eq 'C') && $abort_on_ac_config) { am_conf_line_error($filename, $aclnum, "automake requires AM_CONFIG_HEADER, not AC_CONFIG_HEADER"); } $config_header_line = $aclnum; 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 ($cline =~ /$AM_CONDITIONAL_PATTERN/o) { prt( "[dbg31] $aclnum: [$acline]\n" ) if ($dbg31); if ( defined $cfg_defines{$1} ) { # has been DEFINED in am2dsp?.cfg file, or previously defined prt( "[dbg02] Storing configure_cond key $1 ... value=2\n" ) if ($dbg02); $configure_cond{$1} = 2; } else { prt( "[dbg02] Storing configure_cond key $1 ... value=1\n" ) if ($dbg02); $configure_cond{$1} = 1; } } if ($cline =~ /$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" ); } } prt("Done scan of [$filename]... processed $aclnum lines...\n"); prt("Package = [$dsp_package], version = [$dsp_version]\n"); prt("Full Names: [".join(", ",@config_fullnames)."]\n"); prt("Names: [".join(", ",@config_names)."]\n"); prt("Headers: [".join(", ",@config_headers)."]\n"); prt("Got ".scalar @make_input_list." make input items...\n"); # $make_list{$input} = join(':', ($local,@rest)); if ($dbg47) { foreach $input (@make_input_list) { $nval = $make_list{$input}; prt(" $input = [$nval]\n"); } } # $config_ac_macros{$key} = $nval; prt("Got ".scalar keys(%config_ac_macros)." items in \%config_ac_macros...\n"); $acline = 0; while ($acline < 2) { $acline++; prt("\n[dbg38] Run $acline...\n") if ($dbg38); foreach $key (keys %config_ac_macros) { $one_hdr = $config_ac_macros{$key}; $nval = do_mac_subs($ac_dir,$key,$one_hdr,$acline); if (defined $IN_MACS{$key}) { $cline = $IN_MACS{$key}; if ($nval eq $cline) { prt(" [dbg38] $key = [$nval], no change\n") if ($dbg38); } else { prt(" [dbg38] $key = [$nval], changed from [$cline]\n") if ($dbg38); $IN_MACS{$key} = $nval; } } else { $IN_MACS{$key} = $nval; prt(" [dbg38] $key = [$nval], NEW\n") if ($dbg38); } if ("$one_hdr" ne "$nval") { $config_ac_macros{$key} = $nval; } } } if (length($temp_in_macs)) { # = $perl_dir."\\tempinmac.txt"; $one_hdr = ''; $acline = 0; foreach $key (sort keys %IN_MACS) { $nval = $IN_MACS{$key}; $one_hdr .= " '$key' => "; if ($nval =~ /^\d+$/) { $one_hdr .= "$nval,\n"; } else { $one_hdr .= "'$nval',\n"; } $acline++; } write2file($one_hdr,$temp_in_macs); prtw("WARNING:debug: Written $acline IN_MACS to [$temp_in_macs]...\n"); } ##### pgm_exit(1,"TEMPORARY CHECK"); } sub am_error { my ($msg) = shift; pgm_exit($exit_status,"ERROR: $msg\n"); } sub am_conf_line_error { my (@args) = @_; am_error("am_conf_line_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 ($f,$fi,$fil,$dir); foreach $f (@arr) { $fi = $f; $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]! deps=[$deps]\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 = ''; # generate LIST of SOURCES 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); } } $uproj = unique_proj($proj); prt( "[dbg21] Project:O:1: [$proj] - sources [$srcs] [$uproj]\n" ) if ($dbg21); $other_projs{$uproj} = $srcs; # keep this PROJECT, and SOURCES (both c and h) LIST of SOURCE 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:[dbg45] Using a LOOSE search, since [$proj] nor [$proj2]_SOURCES NOT FOUNT!\n") if ($dbg45); # 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); } } $uproj = unique_proj($proj3); prt( "[dbg21] Project:O:2: [$proj] - sources [$srcs] [$uproj]\n" ) if ($dbg21); $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( "[dbg23] 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) { $uproj = unique_proj($proj); prt( "[dbg21|23] Project:O:3: [$proj] - sources [$srcs] [$uproj]\n" ) if ($dbg21 || $dbg23); $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( "[dbg25] 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( "[dbg25] 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 strip_single_quotes { my ($ln) = shift; if ($ln =~ /^'.*'$/) { $ln = substr($ln,1,length($ln)-2); } return $ln; } sub massage_key($$) { my ($k,$rd) = @_; $k = strip_quotes($k); $k = strip_single_quotes($k); $k = trim_all($k); if ($k =~ /^\$\((.+)\)/) { my $m = $1; if (($m eq 'top_srcdir') || ($m eq 'top_builddir') ) { $k = replace_top_srcdir($k,$rd); } elsif ($k =~ /^\$\((.+)\)$/) { $k = $m; } } return $k; } sub is_skipped_item($) { my $t = shift; return 1 if ($t =~ /^-/); return 1 if ($t eq 'mv'); return 1 if ($t eq '<'); return 1 if ($t eq '>'); return 1 if ($t eq '&&'); return 1 if ($t =~ /^#/); return 1 if ($t =~ /^s#/); return 0; } sub add_2_new_source_list($$$$) { my ($line,$rsa,$rdh,$grp) = @_; my $ok = 0; my $odir = $target_dir; my ($cfil,$cdir) = fileparse($line); my $rdir = get_rel_dos_path($cdir,$odir); my $sfil = $rdir.$cfil; return if (defined ${$rdh}{$sfil}); ${$rdh}{$sfil} = 1; my ($filter,$group); prt("[dbg41] add_2_new_source_list: [$line] grp=[$grp], rel=[$sfil]\n") if ($dbg41); if (is_c_source_extended($line)) { # if (($line =~ /\.cxx$/i) || ($line =~ /\.c$/i) || ($line =~ /\.cpp$/i) || ($line =~ /\.cc$/i)) $filter = get_def_src_filt(); $group = get_def_src_grp(); $ok = 1; } elsif (is_h_source_extended($line)) { # elsif ( ($line =~ /\.hxx$/i) || ($line =~ /\.h$/i) || ($line =~ /\.hpp$/i) ) $filter = get_def_hdr_filt(); $group = get_def_hdr_grp(); $ok = 2; } elsif (is_resource_file($line)) { $filter = get_def_rcs_filt(); $group = get_def_rcs_grp(); $ok = 3; } if ($ok) { # 0, 1 2 3 4=full file name #push(@sources, [ $line, $group, $filter, 0, '' ]); push(@{$rsa}, [ $sfil, $group, $filter, 0, $line ]); if (($ok == 1)||($ok == 2)) { add_2_source_list(subract_source_dir($line),$grp); } } else { if (! defined $discarded{$line}) { prtw("WARNING: CHECK Discarded [$line]\n"); $discarded{$line} = 1; } } #if (@sources) { # $key = 'PROJECT_SRCS'; # ${$hr}{$key} = [@sources]; return $ok; } sub get_proj_name($) { my ($key) = shift; return $key if ($key =~ /^\w+$/); my ($n,$d,$e) = fileparse( $key, qr/\.[^.]*/ ); if ($d =~ /\.(\\|\/)$/) { if ($e eq '.la') { return $n; } } return 'testproj'; } sub process_in_file_contents($$$) { my ($dsp_file,$file_in,$rd) = @_; # search for target 'all' or 'default' my $all = ''; prt("Processing the contents of [$file_in]...\n"); my ($key,$val,@arr,$key2,$val2,@arr2,$key3,$val3,@arr3,$key4,$val4,@arr4); my ($mac,$ok,$key5,$val5,@arr5,$project,$targ); my %keyh = (); my %dupes = (); my %projs = (); my @sources = (); my $rkeys = \%keyh; $project = ''; $targ = ''; $act_rel_directory = $rd; foreach $key (keys %contents) { if ($key eq 'all') { $all .= ' ' if (length($all)); $all .= $contents{$key}; $targ .= ':' if (length($targ)); $targ .= 'all'; } elsif ($key eq 'default') { $all .= ' ' if (length($all)); $all .= $contents{$key}; $targ .= ':' if (length($targ)); $targ .= 'default'; } } if (length($all)) { prt("Examine targets:$targ: [$all]\n"); @arr = split(/\s/,$all); foreach $key (@arr) { $key = massage_key($key,$rd); next if (length($key) == 0); next if (is_skipped_item($key)); $project = get_proj_name($key); %{$rkeys} = (); ${$rkeys}{$key} = 1; if (defined $contents{$key}) { $val = trim_all($contents{$key}); prt("\ntarg:[$key] = [$val]\n") if ($dbg39); @arr2 = split(/\s/,$val); foreach $key2 (@arr2) { $key2 = massage_key($key2,$rd); next if (length($key2) == 0); next if (is_skipped_item($key2)); next if (defined ${$rkeys}{$key2}); # do NOT expand twice ${$rkeys}{$key2} = 1; if (defined $contents{$key2}) { $val2 = trim_all($contents{$key2}); next if (length($val2) == 0); prt(" rule:1:[$key2] = [$val2]\n") if ($dbg39); @arr3 = split(/\s/,$val2); foreach $key3 (@arr3) { $key3 = massage_key($key3,$rd); next if (length($key3) == 0); next if (is_skipped_item($key3)); next if (defined ${$rkeys}{$key3}); # do NOT expand twice ${$rkeys}{$key3} = 1; if (defined $contents{$key3}) { $val3 = trim_all($contents{$key3}); next if (length($val3) == 0); prt(" rule:2:[$key3] = [$val3]\n") if ($dbg39); #---------- @arr4 = split(/\s/,$val3); foreach $key4 (@arr4) { $key4 = massage_key($key4,$rd); next if (length($key4) == 0); next if (is_skipped_item($key4)); next if (defined ${$rkeys}{$key4}); # do NOT expand twice ${$rkeys}{$key4} = 1; if (defined $contents{$key4}) { $val4 = trim_all($contents{$key4}); next if (length($val4) == 0); prt(" rule:3:[$key4] = [$val4]\n") if ($dbg39); #---------- @arr5 = split(/\s/,$val4); foreach $key5 (@arr5) { $key5 = massage_key($key5,$rd); next if (length($key5) == 0); next if (is_skipped_item($key5)); next if (defined ${$rkeys}{$key5}); # do NOT expand twice ${$rkeys}{$key5} = 1; if (defined $contents{$key5}) { $val5 = trim_all($contents{$key5}); next if (length($val5) == 0); prt(" rule:4:[$key5] = [$val5]\n") if ($dbg39); } else { $ok = "NOT DEFINED"; if (-f $key5) { add_2_new_source_list($key5,\@sources,\%dupes,$project); $ok = "FILE"; } prt(" rule:4:[$key5] = $ok\n") if ($dbg39); } } #---------- } else { $ok = "NOT DEFINED"; if (-f $key4) { add_2_new_source_list($key4,\@sources,\%dupes,$project); $ok = "FILE"; } prt(" rule:3:[$key4] = $ok\n") if ($dbg39); } } #---------- } else { $ok = "NOT DEFINED"; if (-f $key3) { add_2_new_source_list($key2,\@sources,\%dupes,$project); $ok = "FILE"; } prt(" rule:2:[$key3] = $ok\n") if ($dbg39); } } } else { $ok = "NOT DEFINED"; if (-f $key2) { add_2_new_source_list($key2,\@sources,\%dupes,$project); $ok = "FILE"; } prt(" rule:1:[$key2] = $ok\n") if ($dbg39); } } } else { $ok = "NOT DEFINED"; if (-f $key) { add_2_new_source_list($key,\@sources,\%dupes,$project); $ok = "FILE"; } prt("targ:[$key] = $ok\n") if ($dbg39); } if (@sources) { if (defined $projs{$project}) { $val = $projs{$project}; push(@{$val},@sources); } else { $projs{$project} = [@sources]; } } @sources = (); %dupes = (); } } else { prtw("WARNING: No target 'all', or 'default' found in [$file_in]\n"); } $val = scalar keys %projs; if ($val) { prt("Found $val projects in [$file_in]...\n"); if ($dbg40) { my ($k,$ra,$min,$len); # foreach $file (@msvc_c_files) { # ##prt( "$file\n" ); # @arr = split(/\|/ , $file); # get Lib | Source | Title foreach $key (keys %projs) { $ra = $projs{$key}; $val = scalar @{$ra}; $min = 0; for ($k = 0; $k < $val; $k++) { #push(@{$rsa}, [ $sfil, $group, $filter, 0, '' ]); $val2 = ${$ra}[$k][0]; $len = length($val2); $min = $len if ($len > $min); } } foreach $key (keys %projs) { $ra = $projs{$key}; $val = scalar @{$ra}; prt("Project $key has $val sources...\n"); for ($k = 0; $k < $val; $k++) { #push(@{$rsa}, [ $sfil, $group, $filter, 0, '' ]); $val2 = ${$ra}[$k][0]; $val3 = ${$ra}[$k][1]; $val2 .= ' ' while (length($val2) < $min); prt("$val2 group:[$val3]\n"); } } } } else { prtw("WARNING: No PROJECTS found in [$file_in]\n"); } ##### pgm_exit(1,"TEMP EXIT TO REVIEW KEY EXPANSION"); } sub process_am_file { my ($dsp_name,$makefile,$rd) = @_; my $base_dir = './'; my $dsp_file = $rd . $dsp_name . '.dsp'; ###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 ) { # if we have an configure.ac file here scan_one_configure_file( $file_ac, $rd ); } #$file_am .= '.am' if !($file_am =~ /\.am$/i); $file_am = get_next_full_am_file($makefile); $current_am_file = sub_common_folder($file_am,$rd); prt( "[dbg24] Processing AM file [$current_am_file]\n" ) if ($dbg24); push(@done_am,$file_am); initialize_per_input(); # clear out previous read_main_am_file($file_am, $rd); # preview the 'contents' to find 'group' $cnt = scalar keys(%contents); prt( "\n[dbg19|28]:CT: Got $cnt items in \%contents from file $file_am...\n" ) if ($dbg28 || $dbg19); $cnt = 0; my $lib_cnt = 0; my $prog_cnt = 0; my $lib_scnt = 0; my $prog_cnt2 = 0; my $src_cnt2 = 0; my $lt_libs = 0; # missing like a2j_client_LTLIBRARIES foreach $key (keys %contents) { $file = trim_all($contents{$key}); @files = split(' ',$file); $fnd = scalar @files; $cnt++; # NOTE this pattern # [dbg19|28]:CT:4: [plugin_LTLIBRARIES] = [jack_sun.la] # [dbg19|28]:CT:5: [jack_sun_la_LDFLAGS] = [-module -avoid-version] # [dbg19|28]:CT:7: [jack_sun_la_SOURCES] = [sun_driver.c sun_driver.h] # so we have a plugin_LTLIBRARIES, so the project name is jack_sun[.la] # and then we have the SOURCES... !!! prt( "[dbg19|28]:CT:$cnt: [$key] = [$file]\n" )if ($dbg28 || $dbg19); if ($key =~ /\s*([\w-]+)_LIBRARIES\s*/) { $lib_cnt++; } elsif ($key =~ /\s*([\w-]+)_LTLIBRARIES\s*/) { $lt_libs++; } elsif ($key =~ /\s*([\w-]+)_PROGRAMS\s*/) { $prog_cnt++; } elsif (($key =~ /lib(.*)_a_SOURCES/) || ($key =~ /lib(.*)_la_SOURCES/) || ($key =~ /libc(.*)_la_SOURCES/) ) { $lib_scnt += $fnd; } elsif ( $key =~ /(.+)_PROGRAMS/) { #if (($key eq 'noinst_PROGRAMS')||($key eq 'bin_PROGRAMS')) { $prog_cnt2 += $fnd; } elsif ($key =~ /(.+)_SOURCES/) { $src_cnt2 += $fnd; } elsif ($key =~ /SUBDIRS/) { # DIST_SUBDIRS $gotsubd += $fnd; } elsif ($key =~ /HEADERS/) { # include_HEADERS, noinst_HEADERS $gotinch += $fnd; } } if ($dbg28 || $dbg19) { if ($lib_cnt || $lib_scnt || $prog_cnt || $src_cnt2 || $lt_libs) { prt( "[dbg19|28]:CT: Done $cnt libs=$lib_cnt, lt_libs=$lt_libs, lib_src=$lib_scnt, prog=$prog_cnt, src=$src_cnt2...\n" ); } else { prt( "[dbg19|28]:CT: Done $cnt No library, programs or sources\n" ); } } if ($act_am_ext =~ /^\.in$/) { process_in_file_contents($dsp_file,$file_am,$rd); $content_by_file{$file_am} = { %contents }; return; } if ($lib_cnt && $prog_cnt) { prtw("WARNING: Present script LOGIC may be FLAWED\n"); } ############################################################### ## process various contents of %contents ############################################################## # 2010-08-29 - This logic is FLAWED - Could be MULTIPLE LIBS and PROGRAMS per Makefile.am # 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 ($dbg08 || $dbg33); $fnd = 1; last; } } } } 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 ($dbg08 || $dbg33); $fnd = 1; last; } } } } } # 10/02/2010 - NO warning IF it has a 'SUBDIRS' entry if (!$fnd && ($gotsubd == 0) && ($gotinch == 0)) { prtw( "WARNING: NO 'GROUP' FOUND in $file_am ...\n" ); } # 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 prt( "[08] Found SOURCES entry for LIBRARY [$key] [$proj]\n" ) if ($dbg08); @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( "[08] Expanding variable $varname ...\n" ) if ($dbg08); foreach (split(' ', $contents{$varname})) { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); } prt( "[08] Done expanding variable $varname ...\n" ) if ($dbg08); } 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 $dbg09; } elsif (is_h_source_ext($ext)) { push(@msvc_h_extra, $file); prt( "Added [$file] to H EXTRA list\n" ) if $dbg09; } else { push(@msvc_o_extra, $file); prt( "Added [$file] to other EXTRA list\n" ) if $dbg09; } } } 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 ); process_other_sources( $file_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( "[20] End_am_file: sources C=$ac_cnt, H=$ah_cnt, O=$of_cnt, from [$file_am]\n" ) if ($dbg20); $content_by_file{$file_am} = { %contents }; } 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 pre_process_in_file($$) { my ($fil,$ra) = @_; my ($line,$mac,$m,$nline,$lncnt); my @narr = (); my %macs = (); $lncnt = scalar @{$ra}; prt("Pre-processing $lncnt lines, from [$fil]...\n"); foreach $line (@{$ra}) { if ($line =~ /^\s*#/) { push(@narr,$line); next; } $nline = $line; while ($nline =~ /\@(\w+)\@/) { $m = $1; $mac = "'".$m."'"; chomp $line; if (defined $IN_MACS{$m}) { $nline =~ s/\@$m\@/$IN_MACS{$m}/; } else { prt("Deal with [$mac], in [$line]\n"); if (defined $macs{$mac}) { $macs{$mac}++; } else { $macs{$mac} = 1; } last; } } push(@narr,$nline); } my @arr = sort keys(%macs); if (@arr) { prt("MACS:\n".join(" => '',\n",@arr)."\n"); $load_log = 1; pgm_exit(1,"The ABOVE need to be ADDED to the LIST in IN_MACS!"); } if (length($temp_in_file)) { write2file(join("",@narr)."\n",$temp_in_file); prtw("WARNING:debug: Written substituded IN file to [$temp_in_file]...\n"); } return @narr; } sub trim_rule($) { my $rule = shift; if (defined $rule && length($rule)) { $rule = trim_all($rule); while ($rule =~ /\\$/) { $rule =~ s/\\$//; $rule = trim_all($rule); } #prt("trim_rule: returning [$rule]\n"); return $rule; } #prt("trim_rule: returning blank\n"); return ''; } 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; } my @am_lines = <AM_FILE>; close AM_FILE; my $am_lncnt = scalar @am_lines; prt( "\nReading [$am_file], $am_lncnt lines (rel_dir=$relative_dir)\n" ) if ($dbg10 || $dbg16 || $dbg19); #my ($am_name, $am_path) = fileparse($am_file); my ($am_name, $am_path, $am_ext) = fileparse($am_file, qr/\.[^.]*/ ); @am_lines = pre_process_in_file($am_file,\@am_lines) if ($am_ext =~ /^\.in$/i); 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 = ''; my ($targ,$rule,$type,$value,$add_it,$disc_it); my $in_if_pattern = 0; # 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 $value = trim_rule($aml); prt( "$aln [$aml]\n" ) if ($dbg10); #if ($aml =~ /^all\s*:/) { # prt("$aln: Got all target [$aml] - set all debug ON! ".($saw_bk ? "saw_bk" : "nobk")."\n"); # set_all_dbg_on(); #} # $_ .= "\n" unless substr ($_, -1, 1) eq "\n"; if ($aml =~ /$IGNORE_PATTERN/o) { prt("[dbg35] $aln:[$aml]: IGNORE_PATTERN\n") if ($dbg35); # Merely delete comments beginning with two hashes. } elsif ($aml =~ /$WHITE_PATTERN/o) { prt("[dbg35] $aln:[$aml]: WHITE_PATTERN\n") if ($dbg35); # Stick a single white line before the incoming macro or rule. $spacing = "\n"; ###am_line_error ($aln, "blank line following trailing backslash") if $saw_bk; am_line_error ($aln, "blank line following trailing backslash") if $saw_bk; } elsif ($aml =~ /$COMMENT_PATTERN/o) { prt("[dbg35] $aln:[$aml]: COMMENT_PATTERN\n") if ($dbg35); # Stick comments before the incoming macro or rule. $comment .= $spacing . $aml; $spacing = ''; if ($error_comment_saw_bk) { ###am_line_error ($aln, "comment following trailing backslash") if $saw_bk; am_line_error ($aln, "comment following trailing backslash") if $saw_bk; } next; } elsif ($saw_bk) { prt("[dbg35] $aln:[$aml]: saw back - continuation line\n") if ($dbg35); # ============================================================ # continuation of previous line(s) ... if ($was_rule) { prt("[dbg35] $aln: was_rule - add to output_trailer, and targ [$targ]\n") if ($dbg35); $output_trailer .= join ('', @conditional_stack) . $aml; if (defined $contents{$targ}) { if (length($value)) { $contents{$targ} .= " $value"; prt("[dbg46] Added to contents:1: [$targ]=[$value]\n") if ($dbg46); } } else { prtw("WARNING: contents{$targ} does NOT EXITS!\n"); } $saw_bk = ($aml =~ /\\$/); } else { prt("[dbg35] $aln: !was_rule last var [$last_var_name]\n") if ($dbg35); $saw_bk = ($aml =~ /\\$/); # 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' ... $add_it = 0; # assume NO $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} .= $value; # $aml; if (@conditional_stack) { prt("[dbg46] Added to contents:2: [$last_var_name]=[$value], and to conditional quoted...\n") if ($dbg46); $conditional{$last_var_name} .= quote_cond_val ($value); } else { prt("[dbg46] Added to contents:2: [$last_var_name]=[$value]\n") if ($dbg46); } prt("[dbg12] $aln:End VAR:[$last_var_name] = [".trim_line($contents{$last_var_name})."]...\n" ) if ( !$saw_bk && $dbg12); } else { if (!$disc_it) { # that is, if NOT a deliberate discard ###push(@warnings, "WARNING: File [$am_file], line $aln, last var [$last_var_name]"); push(@warnings, "WARNING: File [$am_file], line $aln, last var [$last_var_name]"); push(@warnings, " Discarding the [$aml] ... CHECK ME"); if ( defined $contents{$last_var_name} ) { if ( @conditional_stack ) { push(@warnings, " stack = $conditional_stack[$#conditional_stack] cond_true=$cond_true"); } } prtw( "WARNING:1: Discarding this [$aml] ... CHECK ME!\n" ); } else { prtw( "WARNING:2: Discarding this [$aml] ... CHECK ME!\n" ); } } } # =================================================================== } elsif ($aml =~ /$IF_PATTERN/o) { prt("[dbg35] $aln:[$aml]: IF_PATTERN\n") if ($dbg35); 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\@"); $in_if_pattern++; } elsif ($aml =~ /$ELSE_PATTERN/o) { prt("[dbg35] $aln:[$aml]: ELSE_PATTERN\n") if ($dbg35); if (! @conditional_stack) { am_line_error ($aln, "else without if"); } elsif ($conditional_stack[$#conditional_stack] =~ /_FALSE\@$/) { am_line_error ($aln, "else after else"); } else { $conditional_stack[$#conditional_stack] =~ s/_TRUE\@$/_FALSE\@/; } } elsif ($aml =~ /$ENDIF_PATTERN/o) { prt("[dbg35] $aln:[$aml]: ENDIF_PATTERN\n") if ($dbg35); if (! @conditional_stack) { am_line_error ($aln, ": endif without if"); } else { pop @conditional_stack; } $cond_true = 2; # undetermined ... $in_if_pattern-- if ($in_if_pattern); } elsif ($aml =~ /$RULE_PATTERN/o) { # Found a rule, and may be many lines... prt("[dbg35] $aln:[$aml]: RULE_PATTERN [$1] [$2]\n") if ($dbg35); $targ = $1; $rule = trim_rule($2); $was_rule = 1; if (defined $contents{$targ} && (@conditional_stack ? ! defined $conditional{$targ} : defined $conditional{$targ})) { $msg = "[$targ] RULE_PATTERN defined both conditionally and unconditionally.\n"; $value = $contents{$targ}; $msg .= "Defined in contents with value [$value]\n"; if (@conditional_stack) { $value = join(", ",@conditional_stack); $msg .= "There is a conditional_stack, with [$value], but NOT in conditional\n"; } else { $value = $conditional{$targ}; $msg .= "There is NO conditional_stack open, but is defined in conditional as [$value]\n"; } $msg .= "So what is WRONG?"; if ($abort_on_conditional) { am_line_error ($aln, $msg); } else { prtw("WARNING:$aln: $msg CHECK ME!\n"); } } # 2010-09-29: NO VALUE MATTERS Value here doesn't matter; for targets we only note existence. if (defined $contents{$targ}) { $contents{$targ} .= ' '.$rule; } else { $contents{$targ} = $rule; } if (defined $targets{$targ}) { $targets{$targ} .= ' '.$rule; prt("[dbg46] Added to contents:3: [$targ]=[$rule]\n") if ($dbg46); } else { $targets{$targ} = $rule; prt("[dbg46] Added to contents:3: [$targ]=[$rule] SET\n") if ($dbg46); } $cond_string = join ('', @conditional_stack); if (@conditional_stack) { if ($conditional{$targ}) { check_ambiguous_conditional ($targ, $cond_string); $conditional{$targ} .= ' '; } else { $conditional{$targ} = ''; } $conditional{$targ} .= $cond_string . ' 1'; } $content_lines{$targ} = $aln; $output_trailer .= $comment . $spacing . $cond_string . $aml; $comment = $spacing = ''; $saw_bk = ($aml =~ /\\$/); # Check the rule for being a suffix rule. If so, store in # a hash. my $source_suffix; my $object_suffix; if (defined $1 && length($1) && (($source_suffix, $object_suffix) = ($1 =~ $SUFFIX_RULE_PATTERN))) { $suffix_rules{$source_suffix} = $object_suffix; prt("[dbg17] 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) { # 2010-08-26 - especially when process Makefile.in, can have # @ON_WINDOWS@LINK = $(CC) $(LDFLAGS) -I. -I$(top_srcdir) -L.libs #} elsif (($is_ok_macro = ($aml =~ /$MACRO_PATTERN/o)) || #($is_ok_macro = ($aml =~ /$BOGUS_MACRO_PATTERN/o))) { prt("[dbg35] $aln:[$aml]: MACRO_PATTERN\n") if ($dbg35); prt( "[dbg14] line $aln: Found a macro definition. 1[$1] 2[$2] 3[$3] ...\n" ) if ($dbg14); $was_rule = 0; $last_var_name = $1; $type = $2; $value = trim_rule($3); if (defined $contents{$last_var_name} && (@conditional_stack ? !defined $conditional{$last_var_name} : defined $conditional{$last_var_name})) { 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); } if ($type eq '+') { if (! defined $contents{$last_var_name} && defined $configure_vars{$last_var_name}) { $contents{$last_var_name} = '@' . $last_var_name . '@'; } if ( defined $contents{$last_var_name} ) { $contents{$last_var_name} .= ' ' . $value; prt("[dbg46] Added to contents:4: [$last_var_name]=[$value]\n") if ($dbg46); } else { $contents{$last_var_name} = $value; prt("[dbg46] Added to contents:4: [$last_var_name]=[$value] SET\n") if ($dbg46); } } 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 ) { prt( "NB: [$last_var_name] = [$contents{$last_var_name}]" . " replaced with [$value] (am_file=$am_file line=$aln)". (($aml =~ /\\$/) ? "saw_bk" : "end") . "\n" ); } } $contents{$last_var_name} = $value; prt("[dbg46] Added to contents:5: [$last_var_name]=[$value] SET\n") if ($dbg46); $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 ) { prt( "NB: [$last_var_name] = [$contents{$last_var_name}]" . " replaced with [$value] (am_file=$am_file line=$aln)". (($aml =~ /\\$/) ? "saw_bk" : "end") . "\n" ); } } $contents{$last_var_name} = $value; prt("[dbg46] Added to contents:6: [$last_var_name]=[$value] SET\n") if ($dbg46); $content_lines{$last_var_name} = $aln; } } } } else { prt( "First setting [$last_var_name] = [$value] " . "(am_file=$am_file line=$aln) ". (($aml =~ /\\$/) ? "saw_bk" : "end") . "\n" ) if ($dbg15); $contents{$last_var_name} = $value; prt("[dbg46] Added to contents:7: [$last_var_name]=[$value] SET\n") if ($dbg46); # 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} = $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 = ($aml =~ /\\$/); # Error if bogus. am_line_error ($aln, "bad macro name \`$last_var_name'") if (!$is_ok_macro && $exit_bogus_macro); } elsif ($aml =~ /$INCLUDE_PATTERN/o) { my $orgpath = $1; prt("[dbg35] $aln:[$aml]: INCLUDE_PATTERN\n") if ($dbg35); 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 { prt("[dbg35] $aln:[$aml]: UNCASED PATTERN\n") if ($dbg35); # 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) . $aml); $comment = $spacing = ''; $saw_bk = ($aml =~ /\\$/); prt("$aln: UNCASED LINE! [$aml]! ASSUMED was_rule continuations? CHECK ME! ".($saw_bk ? "saw_bk" : "nobk")."\n") if ($dbg36); } } prt( "Done reading of $am_file\n" ) if ($dbg10 || $dbg16 || $dbg19); $output_trailer .= $comment; am_error ("unterminated conditionals: " . join (' ', @conditional_stack)) if (@conditional_stack); $act_am_file = $am_file; $act_am_dir = $am_path; $act_am_ext = $am_ext; } 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 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 list_all_sources { my ($msg,$rd) = @_; my $ac = scalar @all_files; my ($mc,$file,$done,$type,$rfil,$len,$max,$i); $mc = 0; $max = 0; # 0 1 2 3 4 #push(@all_files, [$df, $ff, 0, $typ, $rd]) if ($typ); for ($i = 0; $i < $ac; $i++) { $rfil = $all_files[$i][0]; $done = $all_files[$i][2]; $mc++ if (!$done); $len = length($rfil); $max = $len if ($len > $max); } if ($mc) { prt("First a list of $mc of $ac NOT done...\n"); for ($i = 0; $i < $ac; $i++) { $rfil = $all_files[$i][0]; $file = $all_files[$i][1]; $done = $all_files[$i][2]; $type = $all_files[$i][3]; if (!$done) { prt("File:".get_my_type_stg($type).": $rfil\n"); } } } if ($ac - $mc) { prt("Next a list of ".($ac - $mc)." of $ac done...\n"); for ($i = 0; $i < $ac; $i++) { $rfil = $all_files[$i][0]; $file = $all_files[$i][1]; $done = $all_files[$i][2]; $type = $all_files[$i][3]; if ($done) { prt("File:".get_my_type_stg($type).": $rfil\n"); } } } } sub show_source_list { my ($msg,$rd) = @_; my $ac = scalar @all_files; # 0 1 2 3 4 #push(@all_files, [$df, $ff, 0, $typ, $rd]) if ($typ); my ($mc, $i, $file, $line, $omsg); $mc = 0; my @files = (); my ($nam, $dir, $ext); if (!$ac) { prt("No SOURCES to show!\n"); return; } if ($show_all_sources) { list_all_sources($msg,$rd); return; } # 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); } # This END this DSP file, # but first it also WRITES the HEADERS, if any found 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 any found if (defined $am_headers{$last_project}) { my $lsrcs = $am_headers{$last_project}; my @arr = split(/\|/ , $lsrcs); # Sources foreach my $s (@arr) { $s = loc_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 ($incs, $prj) = @_; 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 ($incs,$prj) = @_; if (defined $am_libadds{$prj}) { $incs .= " " if (length($incs)); $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( $msvc_cflags, $prj ); $msvc_libs = get_am_libs( $msvc_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; # This has already been done before here #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 local_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 ($dbg43); 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 ($dbg43); $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 ($dbg43); ($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 ($dbg43); $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 ($dbg43); } 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_list2($$$) { my ($caller, $fil, $rarr) = @_; my @lines = get_C_file_lines($fil); my $lncnt = scalar @lines; my $inc = ''; prt( "Processing $lncnt lines, from $fil ...\n") if ($dbg44); 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 ($dbg44); } } } sub get_include_list { my ($caller, $sf, $fil, $rarr) = @_; if ( -f $fil ) { get_include_list2($caller, $fil,$rarr); } elsif (-f $sf) { get_include_list2($caller, $sf,$rarr); } else { prtw( "WARNING:caller:$caller: Unable to find [$fil] or sf=[$sf]\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"); } sub process_input_files() { if (@input_files) { @inf = @input_files; prt( "Processing ".scalar @inf." files...\n" ); foreach my $fil (@inf) { if (!does_next_am_file_exist($fil)) { my $msg = "\nERROR: Can NOT proceed. No such makefile [$fil]!"; $msg .= "\n That is, can NOT find an .am file of this name!"; $msg .= "\n Nor an .in file of this name." if ($support_makefile_in); $msg .= "\n This file was indicated during the scanning of 'configure.ac'!\n"; pgm_exit(1,"$msg\n"); } } foreach my $fil (@inf) { process_one_file($fil); } } } sub process_other_files() { @other_inputs = get_missed_makes($main_root_dir); my ($fil_name, $fil_dir, $am_file, $mk); 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 = loc_fix_rel($main_root_dir . $fil_dir); # also returns DOS, minus trailing '\' $full_fil_path .= "\\" if ( !($full_fil_path =~ /\\$/) ); # add trailing '\' IF # 2010-08-26 - This does NOT account for Makefile.in!!! Soooo # but ONLY if $support_makefile_in is ON (-m) #$next_am_file = $afile; #$next_am_file .= ".am" if (has_no_extent($afile) && !is_am_file($afile)); if (!does_next_am_file_exist($afile)) { prtw("WARNING: Skipping no existing [$afile]+extension. ". ($support_makefile_in ? "NO am or in" : "Maybe with -m")."\n"); next; } $next_am_file = get_next_am_file($afile,"process_other_files"); prt( "Processing 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 )); $am_file = get_next_full_am_file($afile); $mk = mark_all_files($am_file); prtw( "WARNING:O: NOT FOUND IN MARK [$am_file]!\n" ) if (!$mk); } } } sub write_upd_bat($$) { my ($ra,$out) = @_; # \@copy_bat,$temp_upd_bat my $cnt = scalar @{$ra}; return if (!$cnt); my ($msg,$i,$tmp,$fin); $msg = "\@echo WARNING: This will overwrite any EXISTING DSP/DSW files in [$target_dir]!\n"; $msg .= "\@echo *** ARE YOU SURE YOU WANT TO CONTINUE? *** Ctrl+C to abort...\n"; $msg .= "\@pause\n"; $msg .= "\@echo *** LAST CHANCE! *** Ctlr+C to abort.\n"; $msg .= "\@pause\n"; for ($i = 0; $i < $cnt; $i++) { $tmp = ${$ra}[$i][0]; $fin = ${$ra}[$i][1]; $msg .= "copy $tmp $fin\n"; } $msg .= "\@echo Copied $cnt files... All done...\n"; write2file($msg,$out); $msg = "NOTICE: Have written an UPDATE batch file to [$out]...\n"; $final_message = $msg; prtw($msg); } ######################################################### ### MAIN ### # set_dbg_rel2(1); set_all_dbg_off(); parse_args(@ARGV); get_top_files( $main_root_dir, 0 ); scan_root_folder( $main_root_dir ); process_input_files(); # 'AC_OUTPUT(...)' 'Makefile.am (or .in) from configure.ac (or .in) ### pgm_exit(1,"REVIEW"); process_other_files(); # 'AC_OUTPUT(...)' Other than 'Makefile.am (or .in) from configure.ac (or .in) $c_cnt = scalar @msvc_c_files; $t_cnt = scalar @msvc_titles; $h_cnt = scalar @msvc_h_files; $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(); $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_source_list( "makefile.am set", $main_root_dir ) if ($show_all_sources || $show_missed_sources); gen_temp_dsw( $main_root_dir ); if ($write_temp_ds && @copy_bat && length($temp_upd_bat) && !$only_dry_run) { write_upd_bat(\@copy_bat,$temp_upd_bat); } pgm_exit($exit_status,""); ### END MAIN ### ######################################## sub give_help { my ($tmp); prt("$pgmname: version 0.3.1 2010-09-22\n"); prt(" Suspended this script in favour of amsrcs04.pl with fuller implementation.\n"); prt("Usage: $pgmname [options] [input-directory]\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt(" --flags <flag> (-f) = Add to defines flag/macro. '-f FOO', to add '/D \"FOO\"' to the compile.\n"); $tmp = get_dbg_range(); prt(" --dbg <num> (-d) = Set DEBUG flag of this value. Number in range 1 to $tmp\n"); prt(" --incs <path> (-i) = Add to includes. '-i .', to add '/I \".\"' tot he compile.\n"); prt(" --load_log (-l) = Load log at end, using default 'txt' editor.\n"); prt(" --make_in (-m) = Add support for Makefile.in parsing, but this is not complete.\n"); prt(" --out <opt> (-o) = Output list of sources, indicating if 'main' found. opt='all' or 'missed'\n"); # prt(" --proj <name> (-p) = Set project name'.\n"); prt(" --resp <file> (-r) = Commands from a reponse/input file.\n"); prt(" --src <dir> (-s) = Source directory to scan.\n"); prt(" --targ <dir> (-t) = Target directory for DSP file.\n"); prt("PURPOSE:\n"); prt(" Scan the target directory for 'configure.ac', and process for valid 'projects',\n"); prt(" and write a temp.proj_name.DSP file for each project found.\n"); prt("NOTES:\n"); prt(" If no input directory is given, then the current directory will be used.\n"); prt(" If no target directory given, then the input directory will be used, and each DSP\n"); prt(" will be relative to this target directory.\n"); prt(" The input file is a set of line delimited commands. Lines beginning with '#' are skipped.\n"); prt("\n"); prt(" The debug switch is strictly for that. It adds no functionality, just a noisier output,\n"); prt(" and has the text settings of 'all', 'none', or 'help', to show the list in more detail.\n"); prt(" And there is another, namely 'dry-run', to do all the scanning, but do NOT write DSW/DSP file.\n"); $tmp = get_dbg_stg(); prt(" For debug, presently values [$tmp] are ON\n") if (length($tmp)); prt(" For debug, the pre-processed Makefile.in will be written to [$temp_in_file]\n") if (length($temp_in_file)); prt(" For debug, the adjusted IN_MACS will be written to [$temp_in_macs].\n") if (length($temp_in_macs)); } sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av); } sub show_dbg_help() { my $file = $0; my ($line,$max,$tmp,$cnt); $max = get_dbg_range(); $tmp = get_dbg_stg(); prt(" --dbg <num> (-d) = Set DEBUG flag of this value. Number in range 1 to $tmp\n"); prt(" Presently %tmp are ON.\n") if (length($tmp)); prt(" Additional text setting are 'all', 'none', and this 'help'.\n"); if (open INF, "<$file") { my @lines = <INF>; close INF; prt(" Detailed list, with some 'notes' indicating what each does.\n"); $cnt = 0; foreach $line (@lines) { $line = trim_all($line); if ($line =~ /^my\s+\$dbg(\d+)\s*=\s*\d+\s*;\s*(.+)$/) { $tmp = $1; prt("$tmp: $line\n"); $cnt++; } } prt("ERROR: Found no \$dbg??vars in open file [$file], so NO DEBUG ADDITIONAL HELP!\n") if (!$cnt); } else { prt("ERROR: Unable to open file [$file], so NO DEBUG ADDITIONAL HELP!\n"); } } sub set_cmd_line { my (@av) = @_; my ($arg); foreach $arg (@av) { $cmd_line .= " " if (length($cmd_line)); $cmd_line .= $arg; } } my $in_load_input = 0; sub load_input_file($$) { my ($arg,$file) = @_; if (open INF, "<$file") { my @lines = <INF>; close INF; my @carr = (); my ($line,@arr); foreach $line (@lines) { $line = trim_all($line); next if (length($line) == 0); next if ($line =~ /^#/); @arr = split(/\s/,$line); push(@carr,@arr); } $in_load_input = 1; parse_args(@carr); $in_load_input = 0; } else { pgm_exit(1,"ERROR: Unable to 'open' file [$file]!\n") } } sub add_to_defines($$) { my ($arg,$def) = @_; my $add = "/D \"$def\""; $msvc_cflags .= ' ' if (length($msvc_cflags)); $msvc_cflags .= $add; prt("With $arg, added [$add]\n"); } sub add_to_includes($$) { my ($arg,$def) = @_; my $add = "/I \"$def\""; $msvc_cflags .= ' ' if (length($msvc_cflags)); $msvc_cflags .= "/I \"$def\""; prt("With $arg, added [$add]\n"); } sub parse_args { my (@av) = @_; my ($arg,$sarg,$tmp); set_cmd_line(@av); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^f/i) { # flags (defines) need_arg(@av); shift @av; $sarg = $av[0]; add_to_defines($arg,$sarg); } elsif ($sarg =~ /^i/i) { # includes need_arg(@av); shift @av; $sarg = $av[0]; add_to_includes($arg,$sarg); } elsif ($sarg =~ /^r/i) { # response file need_arg(@av); shift @av; $sarg = $av[0]; load_input_file($arg,$sarg); } elsif ($sarg =~ /^m/i) { $support_makefile_in = 1; prt("Adding Makefile.in support, but not completed!\n"); } elsif ($sarg =~ /^t/i) { need_arg(@av); shift @av; $sarg = $av[0]; $target_dir = File::Spec->rel2abs($sarg); prt("Set target directory to [$target_dir]\n"); pgm_exit(1,"ERROR: Target DIRECTORY does NOT EXIST!\n") if (! -d $target_dir); } elsif ($sarg =~ /^o/i) { need_arg(@av); shift @av; $sarg = $av[0]; if ($sarg =~ /^all$/i) { $show_all_sources = 1; } elsif ($sarg =~ /^missed$/i) { $show_missed_sources = 1; } else { pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Only 'all' or 'missed' allowed!\n"); } } elsif ($sarg =~ /^s/i) { need_arg(@av); shift @av; $sarg = $av[0]; $main_root_dir = File::Spec->rel2abs($sarg); prt("Set input to [$main_root_dir]\n"); } elsif ($sarg =~ /^d/i) { need_arg(@av); shift @av; $sarg = $av[0]; $tmp = get_dbg_range(); if (($sarg =~ /^\d+$/)&&($sarg >= 1)&&($sarg <= $tmp)) { $tmp = 'dbg'; if ($sarg < 10) { $tmp .= "0$sarg"; } else { $tmp .= "$sarg"; } set_dbg_var($sarg); prt("Set Debug $tmp ON!\n"); } else { if ($sarg =~ /^\d+$/) { pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Out of range 1 - $tmp\n"); } else { if ($sarg =~ /^help$/i) { show_dbg_help(); pgm_exit(0,"DEBUG Help exit(0)\n"); } elsif ($sarg =~ /^all$/i) { prt("Setting ALL debug ON!\n"); set_all_dbg_on(); } elsif ($sarg =~ /^none$/i) { prt("Setting ALL debug OFF!\n"); set_all_dbg_off(); } elsif ($sarg =~ /^dry-run$/i) { prt("Setting DRY RUN ONLY!\n"); $only_dry_run = 1; $out_dsp = 0; $out_dsp2 = 0; } else { pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Not numerical in range 1 - $tmp, nor 'all', 'none', 'help' or 'dry-run'!\n"); } } } } elsif ($sarg =~ /^l/i) { prt("Setting Load log at end.\n"); $load_log = 1; } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { $main_root_dir = File::Spec->rel2abs($arg); prt("Set input to [$main_root_dir]\n"); } shift @av; } return if ($in_load_input); if ((length($main_root_dir) == 0) && $debug_on) { $main_root_dir = $def_in_dir; set_all_dbg_on(); } if (length($main_root_dir) == 0) { if ($use_current_dir) { $main_root_dir = path_u2d($cwd); prt("Setting input to CURRENT [$main_root_dir]\n"); } else { pgm_exit(1,"ERROR: No input root directory found in command!\n"); } } $main_root_dir .= "\\" if ( !($main_root_dir =~ /(\\|\/)$/) ); if (length($target_dir) == 0) { $target_dir = $main_root_dir; prt("Set target directory to [$target_dir], based on main ROOT directory.\n"); } pgm_exit(1,"ERROR: Root [$main_root_dir] does NOT continain a 'configure.ac' file!\n") if (!test_root_folder($main_root_dir)); } # eof - amsrcs03.pl