#!/usr/bin/perl # am2dsp8.pl # AIM: Read Makefile.am set, and generate MSVC6 DSW/DSP files for the project. # 13/09/2010 - Suspended this line of scripts for now. See amsrcs04.pl # 24/08/2010 - Review of script # Variable $static_lib controls if app or lib = 1 for SimGear, 0 for FlightGear # ALSO SEE amsrcs[nn].pl to show the sources, and write temp DSP/DSW file # # 21/11/2008 - This will run without a 'config' file, but the results??? # in other attempts at this have used the VCPROJ file to get such values. # Has BIG problem, in that it COMBINES ALL sources, into ONE, including some # of the standalone 'test' and 'utitlity' applications. # # NOTE: Because of changing/evolving spec for config file, am2dsp?.cfg, # this version will not run without finding, at least a blank file am2dsp7.cfg # Also, to simplify the script a little, the writing of the old style DSP, # with 'folders' to match the source folders has been completely abandoned! # also abandoned is the effort to read and modify the MSVC8 solutions files. # geoff mclane - 7 Nov, 2006 # 19/05/2008 - Many changes to try to analyse ANY project, and write DSP/DSW file(s) # # FIX20061107 bug fix: like some JSBSim Makefile.am files, others have been found with # source files listed under 'noinst_HEADERS', this function now only adds # a file from this tag if it has a 'header' extension - h, hpp, or hxx # 20070421 - totally remove all MSVC8 stuff # 21/04/2007 - and do a general tidyup of code # 04/04/2008 - add log file # 2006 geoff mclane http://geoffair.net/mperl # ###################################################################################### use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; my $perl_base = "C:\\GTools\\perl"; unshift(@INC,$perl_base); require 'logfile.pl' or die "Unable to load logfile.pl ...\n"; require 'relative.pl' or die "Unable to load relative.pl ...\n"; # log file stuff my ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $perl_base."\\temp.$pgmname.txt"; open_log($outfile); my $vers = "8"; my $pack = "am2dsp".$vers; # the all important ROOT PATH to process my $root_dir = ''; my $build_dir = ''; my $static_lib = 0; # 1 for SimGear, 0 for FlightGear # debug defaults only my $use_def = 0; # should be OFF in release my $def_root = 'C:\Projects\ftgl-2.1.3'; my $def_build = $def_root; my $def_cfg = "am2dsp".$vers.".cfg"; my $src_cfg = $def_cfg; my $use_cwd_cfg = 0; # also search CWD for config ... my $use_build_dir = 1; # make SOURCE files relative to 'build' folder my $load_log = 0; my $am_file = ''; # String 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]+)\$"; my $MACRO_PATTERN = "^([A-Za-z][A-Za-z0-9_]*)[ \t]*([:+]?)=[ \t]*(.*)\$"; my $BOGUS_MACRO_PATTERN = "^([^ \t]*)[ \t]*([:+]?)=[ \t]*(.*)\$"; my $IF_PATTERN = "^if[ \t]+\([A-Za-z][A-Za-z0-9_]*\)[ \t]*\(#.*\)?\$"; my $ELSE_PATTERN = "^else[ \t]*\(#.*\)?\$"; my $ENDIF_PATTERN = "^endif[ \t]*\(#.*\)?\$"; my $PATH_PATTERN='(\\w|/|\\.)+'; # This will pass through anything not of the prescribed form. my $INCLUDE_PATTERN = "^include[ \t]+((\\\$\\\(top_srcdir\\\)/${PATH_PATTERN})|(\\\$\\\(srcdir\\\)/${PATH_PATTERN})|([^/\\\$]${PATH_PATTERN}))[ \t]*(#.*)?\$"; my $AM_CONDITIONAL_PATTERN = "AM_CONDITIONAL\\((\\w+)"; my $AM_INIT_AUTOMAKE = "AM_INIT_AUTOMAKE\\(([^,]+),[ \t]*([^)]+)"; # AC_INIT (package, version, [bug-report], [tarname]) # Set the name of the package and its version my $AC_INIT = "AC_INIT\\((.+)\\)"; my $AC_DEF = "AC_DEFINE\\((.+)"; my $AC_DEFU = "AC_DEFINE_UNQUOTED\\((.+)"; my $AC_DEFINE = "AC_DEFINE\\((.+)\\)"; my $AC_DEFINE_UNQ = "AC_DEFINE_UNQUOTED\\((.+)\\)"; # Hash table of AM_CONDITIONAL variables seen in configure. my %configure_cond = (); # This holds the names which are targets. These also appear in # %contents. my %targets = (); # This holds the line numbers at which various elements of # %contents are defined. my %content_lines = (); my %content_seen = (); # This maps the source extension of a suffix rule to its # corresponding output extension. my %suffix_rules = (); # Hash table of discovered configure substitutions. Keys are names, # values are `FILE:LINE' strings which are used by error message # generation. my %configure_vars = (); # This holds the set of included files. my @include_stack = (); my $verbose = 0; my $vcond; my @conditional_stack = (); my %contents = (); # after scan of Makefile.am my %conditional = (); # This holds our (eventual) exit status. We don't actually exit until # we have processed all input files - except when 'critical' ... my $exit_status = 0; my @make_input_list = (); my %make_list = (); # Names used in AC_CONFIG_HEADER call. @config_fullnames holds the # name which appears in AC_CONFIG_HEADER, colon and all. # @config_names holds the file names. @config_headers holds the '.in' # files. Ordinarily these are similar, but they can be different if # the weird "NAME:FILE" syntax is used. my @config_fullnames = (); my @config_names = (); my @config_headers = (); # Line number at which AC_CONFIG_HEADER appears in configure.ac. my $config_header_line = 0; # Relative location of top build directory. my $top_builddir = ''; my $relat_dir = '.'; my $output_vars = ''; my $output_trailer = ''; # List of Makefile.am's to process, and their corresponding outputs. my @input_files = (); my %output_files = (); # List of files in AC_OUTPUT without Makefile.am, and their outputs. my @other_input_files = (); my @var_list = (); my %am_vars = (); my %def_type = (); my @excluded_dirs = (); my @excluded_files = (); my $msvc_cflags = ""; my $msvc_threads = ""; my $msvc_libs = ""; my @extra_sources = (); my @extra_projects = (); my %used_inc_paths = (); my %used_lib_paths = (); # new variables my $verbose2 = 0; my $verbose3 = 1; my $msvc_dlibs = ""; my $msvc_rlibs = ""; my $in_debug = 0; my $in_release = 0; my $do_check = 0; my @msvc_dlibs_list = (); my @msvc_rlibs_list = (); my @msvc_libs_list = (); my @msvc_dlibs_paths = (); my @msvc_rlibs_paths = (); my @msvc_libs_paths = (); my @msvc_inc_paths = (); my @test_headers = ( 'zlib.h', 'AL/al.h', 'AL/alut.h', 'simgear/compiler.h', 'simgear/debug/logstream.hxx', 'plib/pu.h', 'Main/main.hxx', 'config.h', 'include/general.hxx', 'FGJSBBase.h'); my $add_groups = 0; # default to single, put duplicates 'Dupes' folder ... my @msvc_c_files = (); my @msvc_h_files = (); my @msvc_titles = (); # just to deal with duplicate names # EXTRA_DIST file lists from Makefile.am list my @msvc_c_extra = (); my @msvc_h_extra = (); my @msvc_o_extra = (); my @am_source_list = (); my $err_msg = ''; # am2dsp?.cfg define = AAA my %cfg_defines = (); # configure.ac equivalent my %def_defines = ( 'FG_JPEG_SERVER', 'ENABLE_JPEG_SERVER' ); my %config_ac_macros = (); my @ignore_folders = qw( utils\\fgadmin ); # Extracted from AC_INIT, or # AM_INIT_AUTOMAKE(package,version) my $dsp_package = 'FGFS'; my $dsp_version = '0.2'; # debug items my $debug_on = 0; my $debug_on3 = 0; my $sw_dbg = 0; my $dbg10 = 0; # show EACH line in configure.ac parse my $dbg11 = 0; # show "Split to $vlen components ... my $dbg12a = 0; # show prt( "Adding $input [$ff] to make_input_list ... - items added to @make_input_list my $dbg12b = 0; # show items added to @other_input_list my $dbg13 = 0; # show ac_output_line information ... my $dbg14 = 0; # prt( "Variable $key=$nval\n" my $dbg15 = 0; # prt( "Copying " . scalar @make_input_list . " make_input_list to input_files.\n" ) if ($verbose2 || $dbg15); my $dbg16 = 0; # prt( "Substitute $key=$nval\n" ) if ((($orgkey ne $key)||($orgnval ne $nval)) && $dbg16); my $dbg17 = 0; # prt( "\nProcessing [$am_file] from input_files array ...\n" ) if ($verbose2 || $dbg17); my $dbg18 = 0; # prt( "process_am_file: using dsp_name=$dsp_file, and makefile=$makefile ...\n" ) if ($verbose2 || $dbg18); my $dbg19 = 1; # prt( "$pack: reading $am_file\n" ) if ($verbose || $dbg19); my $dbg20 = 0; # prt( "$. [$aml]\n" ) if ($debug_on3 || /$dbgnn/); my $dbg21 = 0; # prt( "Found a macro definition. 1[$1] 2[$2] 3[$3] ...\n" ) if ($debug_on3 || /$dbgnn/); my $dbg22 = 0; # show_contents() if (/$dbgnn/); my $dbg23 = 0; # show contents of %config_ac_macros my $dbg24 = 0; # prt( "$. Should JOIN lines? - [$cline]\n" ) if (/$dbgnn/); my $dbg25 = 0; # prt( "ADDING SOURCE: $file ($dsp_name, $group, $dup)\n" ) if (/$dbgnn/); my $dbg26 = 0; # prt( "$. Got AC_INIT = [$1]\n" ) if (/$dbgnn/); my $dbg27 = 1; # some of the same as $debug_on3 my @warnings = (); # re-show any WARNINGS at end ... my $cwdir = getcwd(); sub show_warnings { my $wcnt = scalar @warnings; if ($wcnt) { prt( "\nThere are $wcnt lines of WARNINGS ...\n" ); foreach my $wn (@warnings) { prt("$wn\n"); } } else { prt( "There are NO warnings ...\n" ); } prt("\n"); } sub pgm_exit($$) { my ($val,$msg) = @_; if (length($msg)) { $msg .= "\n" if (!($msg =~ /\n$/)); prt($msg) } show_warnings(); close_log($outfile,$load_log); exit($val); } sub add_group_start { my $dsp_name = shift; ##my $dsp_file = $root_dir . $dsp_name . '.dsp'; my $dsp_file = get_dsp_name($dsp_name); open(DSP, ">>$dsp_file") || pgm_exit(1,"ERROR: Can't append to $dsp_file: $!\n"); print DSP "# Begin Group \"Source Files\"\n"; print DSP "\n"; print DSP "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;h;hpp;hxx;hm;inl\"\n"; close(DSP); } sub add_group_end { my $dsp_name = shift; ##my $dsp_file = $root_dir . $dsp_name . '.dsp'; my $dsp_file = get_dsp_name($dsp_name); open(DSP, ">>$dsp_file") || pgm_exit(1,"ERROR: Can't append to $dsp_file: $!\n" ); print DSP "# End Group\n"; close(DSP); } sub exclude_dir { my $dir = shift; foreach my $d (@excluded_dirs) { if ($dir =~ "/$d/") { return 1; } } return 0; } sub exclude_file { my $file = shift; foreach my $f (@excluded_files) { if ($file =~ /$f/) { return 1; } } return 0; } sub add_2_msvc { my $flg = shift; if ($in_debug) { $msvc_dlibs .= $flg; } elsif ($in_release) { $msvc_rlibs .= $flg; } else { $msvc_libs .= $flg; } } sub add_2_libs { my $flg = shift; if ($in_debug) { push(@msvc_dlibs_list, $flg); } elsif ($in_release) { push(@msvc_rlibs_list, $flg); } else { push(@msvc_libs_list, $flg); } } sub add_2_libpaths { my $flg = shift; if ($in_debug) { push(@msvc_dlibs_paths, $flg); } elsif ($in_release) { push(@msvc_rlibs_paths, $flg); } else { push(@msvc_libs_paths, $flg); } } sub read_am2dsp_rc { my $rc_file = shift; prt( "Processing RC FILE [$rc_file] ...\n" ); if ( !open( RC_FILE, $rc_file ) ) { $err_msg = "WARNING: Can't open $rc_file: $!\n"; prtw($err_msg); return; } my $line; my $lncnt = 0; my @cond_stack = (); while (defined($line = )) { chomp $line; $lncnt++; if ($line =~ s/\\$//) { # continuation line $line .= "%"; $line .= ; redo unless eof(RC_FILE); } prt( "Processing line [$line] ...\n" ) if ($debug_on3); next if $line =~ /^$/; # ignore blank lines next if $line =~ /^#/; # ignore comments if ($line =~ /exclude_dir\s*=\s*(\S+)/) { push( @excluded_dirs, $1 ); } elsif ($line =~ /exclude_file\s*=\s*(\S+)/) { my $f; ($f = $1) =~ s/\\/\\\\/g; # escape path separators, "\" -> "\\" push( @excluded_files, $f ); prt( "Excluding file: $f\n" ) if $verbose; } elsif ($line =~ /include_path\s*=\s*(\S+)/) { $msvc_cflags .= " /I \"$1\""; push(@msvc_inc_paths, $1); } elsif ($line =~ /add_vc8_path\s*=\s*(\S+)/) { prt( "ERROR: Line $lncnt: Invalid CONFIG line [$line]! ...\n" ); pgm_exit(1,"ERROR: Got from VC8 to root path: [$1] ... this has been abandoned!\n" ); } elsif ($line =~ /define\s*=\s*(\S+)/) { if ($debug_on) { if (defined $def_defines{$1} ) { prt( "Got define of $1 ... which is $def_defines{$1} ...\n" ); $cfg_defines{$def_defines{$1}} = 1; # add configure.ac } else { prt( "Got define of $1 ...\n" ); } if ( defined $cfg_defines{$1} ) { prt( "Warning: cfg_defines of $1 already defined ...\n" ); } } $cfg_defines{$1} = 1; $msvc_cflags .= " /D \"$1\""; } elsif ($line =~ /lib_path\s*=\s*(\S+)/) { add_2_msvc( " /libpath:\"$1\"" ); add_2_libpaths( "$1" ); } elsif ($line =~ /add_lib\s*=\s*(\S+)/) { add_2_msvc( " $1.lib" ); add_2_libs( "$1.lib" ); } elsif ($line =~ /type\s*=\s*(\S+)/) { my ($type,$threads,$debug) = split /,/, $1; prt( "type=$type, threading=$threads, debug=$debug\n" ); # if $verbose; if ($type =~ "ConsoleApplication") { $static_lib = 0 } elsif ($type =~ "StaticLibrary") { $static_lib = 1 } else { # Invalid type pgm_exit(1,"ERROR: INVALID TYPE IN $rc_file FILE!\n"); } my $flags = " /ML"; # single threaded. if ($threads =~ /Multithreaded/) { $flags = " /MT"; } elsif ($threads =~ /Singlethreaded/) { $flags = " /ML"; } else { # Invalid threading option. pgm_exit(1,"ERROR: INVALID THREADING IN $rc_file FILE!\n"); } if ($debug =~ /Debug/) { $flags .= "d"; } $msvc_cflags .= $flags; } elsif ($line =~ /add_source_file\s*=\s*(.*)/) { my $rule; ($rule = $1) =~ s/%/\n/g; push( @extra_sources, $rule ); } elsif ($line =~ /add_project\s*=\s*(.*)/) { push( @extra_projects, $1 ); } elsif ($line =~ /$IF_PATTERN/o) { my $ifcond = $1; if ($ifcond =~ /Debug/io) { prt( "Entering DEBUG ...\n" ) if $verbose2; $in_debug = 1; $in_release = 0; } elsif ($ifcond =~ /Release/io) { prt( "Entering RELEASE ...\n" ) if $verbose2; $in_release = 1; $in_debug = 0; } else { prt( "EEK! Got $ifcond ...\n" ); pgm_exit(1, "ERROR: Presently ONLY if switch is 'Debug' or 'Release'!\n" ); } push (@cond_stack, "\@" . $ifcond . "_TRUE\@"); } elsif ($line =~ /$ELSE_PATTERN/o) { if (! @cond_stack) { pgm_exit(1,"ERROR: else without if!\n" ); } elsif ($cond_stack[$#cond_stack] =~ /_FALSE\@$/) { pgm_exit(1,"ERROR: else after an else!\n" ); } else { if ($in_debug) { prt( "Switch to RELEASE ...\n" ) if $verbose2; $in_debug = 0; $in_release = 1; } else { prt( "Switch to DEBUG ...\n" ) if $verbose2; $in_debug = 1; $in_release = 0; } $cond_stack[$#cond_stack] =~ s/_TRUE\@$/_FALSE\@/; } } elsif ($line =~ /$ENDIF_PATTERN/o) { if (! @cond_stack) { pgm_exit(1,"ERROR: endif without if!\n" ); } prt( "Exit $cond_stack[$#cond_stack] ...\n" ) if $verbose2; pop (@cond_stack); $in_debug = 0; $in_release = 0; } } # end while close(RC_FILE); prt( "Done RC FILE [$rc_file] ...\n" ); } sub scan_configure { ################################ ### SCANNING configure files ### my $conf_file = ''; my ($key, $val, $cnt); my $ff = $root_dir; $ff .= 'configure.ac'; if ( -f $ff) { $conf_file = $ff; prt( "Scanning [$ff] file ...\n" ); scan_one_configure_file($ff); } else { # if (! -f $ff) { $ff .= '.in'; if (-f $ff) { $conf_file = $ff; prt( "Scanning [$ff] file ...\n" ); scan_one_configure_file($ff); } else { $ff = $root_dir; $ff .= 'configure.in'; if (-f $ff) { $conf_file = $ff; prt( "Scanning [$ff] file ...\n" ); scan_one_configure_file($ff); } } } prt( "End scan of [$conf_file] ...\n" ); ################################# $ff = $root_dir; $ff .= 'aclocal.m4'; if ( -f $ff) { prt( "Scanning [$ff] file ...\n" ); scan_one_configure_file($ff); } if ( ! @input_files ) { prt( "Copying " . scalar @make_input_list . " make_input_list to input_files.\n" ) if ($verbose2 || $dbg15); @input_files = @make_input_list; %output_files = %make_list; } if ( ! @input_files ) { $ff = $root_dir; $ff .= "\\" if ( !($ff =~ /[\\\/]$/) ); $ff .= 'Makefile.am'; if (-f $ff) { $ff = $root_dir; $ff .= "\\" if ( !($ff =~ /[\\\/]$/) ); $ff .= 'Makefile'; prt( "Adding Makefile found ...\n" ); ##push(@input_files, 'Makefile'); push(@input_files, $ff); } } prt( "\@input_files has list of " . scalar @input_files . " makefiles ...\n" ); ## if $verbose2; if ($verbose2) { $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" ); } prt("\n"); # $config_ac_macros{$key} = $nval; if ($dbg23) { $cnt = scalar keys(%config_ac_macros); prt( "Showing $cnt MACROS from $conf_file ...\n" ); foreach $key (keys %config_ac_macros) { $val = trim_all($config_ac_macros{$key}); prt("$key=$val\n"); } prt("\n"); } } sub add_2_ac_macros { my ( $key, $val ) = @_; $config_ac_macros{$key} = $val; } sub trim_all2 { my ($txt) = shift; $txt = trim_all($txt); if ($txt =~ /^\[.+\]$/) { $txt = substr($txt,1,length($txt)-2); } $txt = trim_all($txt); return $txt; } # scanning a configureation file sub scan_one_configure_file { my $filename = shift; if (!open(CONFIGURE, $filename)) { $err_msg = "WARNING: can't open '$filename': $!\n"; prtw($err_msg); return; } prt( "$pack: reading $filename\n" ) if $verbose; my $in_ac_output = 0; my $ac_output_line = ''; my $ff = ''; my $cline = ''; my $rawline = ''; my %var_hash = (); my ($key, $nval, $orgkey, $orgnval, @varr, $vlen, $i, $ky); while () { $cline = $_; # get current line chomp $cline; $rawline = trim_all($cline); ###prt( "$cline\n" ); # Remove comments from current line. s/\bdnl\b.*$//; s/\#.*$//; $cline =~ s/\bdnl\b.*$//; $cline =~ s/\#.*$//; next if (length($cline) == 0); ###prt( "$cline\n" ) if ($dbg10); prt( "$rawline\n" ) if ($dbg10 && length($rawline)); if ($cline =~ /^(\w+)="(\d+)"$/) { prt( "Num Variable $1=$2\n" ); $var_hash{$1} = $2; ###} elsif ($cline =~ /^(\w+)="(.+)"$/) { } elsif ($cline =~ /^(\w+)=(.+)$/) { $key = $1; $nval = $2; $orgkey = $key; $orgnval = $nval; $nval = substr($nval,1,length($nval)-2) if ($nval =~ /^".*"$/); prt( "Variable $key=$nval\n" ) if ($dbg14); if (index($nval,'.') != -1) { @varr = split(/\./,$nval); $nval = ''; $vlen = scalar @varr; prt( "Split to $vlen components ...\n" ) if ($dbg11); for ($i = 0; $i < $vlen; $i++) { $ky = trim_line($varr[$i]); prt( "Conponent $ky\n" ) if ($dbg11); if (substr($ky,0,1) eq '$') { $ky = substr($ky,1); if (defined $var_hash{$ky}) { $nval .= '.' if (length($nval)); $nval .= $var_hash{$ky}; } else { $nval .= '.' if (length($nval)); $nval .= $ky; } } else { $nval .= '.' if (length($nval)); $nval .= $ky; } } } prt( "Substitute $key=$nval\n" ) if ((($orgkey ne $key)||($orgnval ne $nval)) && $dbg16); $var_hash{$key} = $nval; $config_ac_macros{$key} = $nval; } elsif ($cline =~ /^\s+(\w+)=(.+)$/) { ### prt( "Line [$cline] NOT USED ...\n" ); # there are lots of them ... } # Skip macro definitions. Otherwise we might be confused into # thinking that a macro that was only defined was actually # used. next if /AC_DEFUN/; if ((/$AC_DEF/) && !(/$AC_DEFINE/)) { # indicates should add next line, until complete $cline = $_; # get current line chomp $cline; prt( "$. Should JOIN lines? - [$cline]\n" ) if ($dbg24); $_ = ; if ($_) { $ky = $cline . ' ' . $_; $_ = $ky; chomp $ky; prt( "$. JOINED - [$ky]\n" ) if ($dbg24); } } elsif ((/$AC_DEFU/) && !(/$AC_DEFINE_UNQ/)) { # indicates should add next line, until complete $cline = $_; # get current line chomp $cline; prt( "$. Should JOIN lines? - [$cline]\n" ) if ($dbg24); $_ = ; if ($_) { $ky = $cline . ' ' . $_; $_ = $ky; chomp $ky; prt( "$. JOINED - [$ky]\n" ) if ($dbg24); } } if (/$AC_INIT/) { prt( "$. Got AC_INIT = [$1]\n" ) if ($dbg26); @varr = split(',', $1); $vlen = scalar @varr; for ($i = 0; $i < $vlen; $i++) { $nval = trim_all($varr[$i]); if ($i == 0) { $nval =~ s/\s/_/g; add_2_ac_macros('PACKAGE_NAME', $nval); $dsp_package = $nval; } elsif ($i == 1) { add_2_ac_macros('PACKAGE_VERSION', $nval); add_2_ac_macros('PACKAGE_STRING', $config_ac_macros{'PACKAGE_NAME'} .' ' .$nval ); $dsp_version = $nval; } elsif ($i == 2) { add_2_ac_macros('PACKAGE_BUGREPORT', $nval); } elsif ($i == 3) { add_2_ac_macros('PACKAGE_TARNAME', $nval); } else { $err_msg = "WARNING: $i Split of AC_INIT = $nval\n"; prtw($err_msg); } } next; } elsif (/$AC_DEFINE/) { prt( "$. Got AC_DEFINE = [$1]\n" ) if ($dbg26); @varr = split(',', $1); $vlen = scalar @varr; if ($vlen >= 2) { $ky = trim_all2($varr[0]); $nval = trim_all2($varr[1]); add_2_ac_macros( $ky, $nval ); } next; } elsif (/$AC_DEFINE_UNQ/) { prt( "$. Got AC_DEFINE_UNQUOTED = [$1]\n" ) if ($dbg26); @varr = split(',', $1); $vlen = scalar @varr; if ($vlen >= 2) { $ky = trim_all2($varr[0]); $nval = trim_all2($varr[1]); add_2_ac_macros( $ky, $nval ); } next; } # Follow includes. This is a weirdness commonly in use at # Cygnus and hopefully nowhere else. if (/sinclude\((.*)\)/ && -f ($root_dir . $1)) { $ff = $root_dir . $1; scan_one_configure_file ($ff); } if (! $in_ac_output && ( s/AC_OUTPUT\s*\(\[?// || s/AC_CONFIG_FILES\s*\(\[?// ) ) { $in_ac_output = 1; $ac_output_line = $.; # get LINE number prt( "Got ac_output_line = line $ac_output_line ... [$rawline]\n" ) if ($dbg13); } if ($in_ac_output) { my $closing = 0; if (s/[\]\),].*$//) { $in_ac_output = 0; $closing = 1; prt( "ac_out: $rawline- CLOSING\n" ) if ($dbg13); } else { prt( "ac_out: $rawline\n" ) if ($dbg13); } # Look at potential Makefile.am's foreach (split) { # Must skip empty string for Perl 4. next if $_ eq "\\" || $_ eq ''; my ($local,$input,@rest) = split(/:/); if (! $input) { $input = $local; } else { $input =~ s/\.in$//; } $ff = $root_dir . $input . '.am'; if (-f $ff) { prt( "Adding $input [$ff] to make_input_list ...\n" ) if ($verbose2 || $dbg12a); push(@make_input_list, $input); $make_list{$input} = join(':', ($local,@rest)); } else { prt( "Adding $input [$ff] to other_input_files ...\n" ) if ($verbose2 || $dbg12b); # We have a file that automake should cause to be # rebuilt, but shouldn't generate itself. push (@other_input_files, $_); } } } # Handle configuration headers. A config header of `[$1]' # means we are actually scanning AM_CONFIG_HEADER from # aclocal.m4. if (/A([CM])_CONFIG_HEADER\s*\((.*)\)/ && $2 ne '[$1]') { &am_conf_line_error ($filename, $., "\`automake requires \`AM_CONFIG_HEADER', not \`AC_CONFIG_HEADER'") if $1 eq 'C'; $config_header_line = $.; my ($one_hdr); foreach $one_hdr (split (' ', $2)) { push (@config_fullnames, $one_hdr); if ($one_hdr =~ /^([^:]+):(.+)$/) { push (@config_names, $1); push (@config_headers, $2); } else { push (@config_names, $one_hdr); push (@config_headers, $one_hdr . '.in'); } } } if (/$AM_CONDITIONAL_PATTERN/o) { if ( defined $cfg_defines{$1} ) { # has been DEFINED in am2dsp?.cfg file prt( "Storing configure_cond key $1 ... value=2\n" ) if ($debug_on3); $configure_cond{$1} = 2; } else { prt( "Storing configure_cond key $1 ... value=1\n" ) if ($debug_on3); $configure_cond{$1} = 1; } } if (/$AM_INIT_AUTOMAKE/o) { $dsp_package = $1; $dsp_version = $2; $dsp_package = do_macro_sub($dsp_package); $dsp_version = do_macro_sub($dsp_version); prt( "Set DSP package = $dsp_package, DSP version = $dsp_version ...\n" ); } } close(CONFIGURE); } sub show_contents { prt( "Showing contents of \%content ...\n" ); # This holds the contents of a Makefile.am, as parsed by # read_am_file. #%contents = (); foreach my $key (keys %contents) { my $val = trim_all($contents{$key}); prt( "$key = $val\n" ); } } sub read_main_am_file { $am_file = shift; read_am_file($am_file); my @topdir = (); foreach (split(/\//, $relat_dir)) { next if $_ eq '.' || $_ eq ''; if ($_ eq '..') { pop @topdir; } else { push(@topdir, '..'); } } @topdir = ('.') if ! @topdir; my $top_builddir = join('/', @topdir); show_contents() if ($dbg22); } sub read_am_file { $am_file = shift; if( ! open( AM_FILE, $am_file ) ) { prtw( "WARNING: Can't open $am_file: $!\n" ); return; } prt( "$pack: reading $am_file\n" ) if ($verbose || $dbg19); 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 ($incfile, $path); while () { 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; while ($_) { my $aml = $_; chomp $aml; $aml =~ s/\r$//; # and remove CR, if present prt( "$. [$aml]\n" ) if ($debug_on3 || $dbg20); $_ .= "\n" unless substr ($_, -1, 1) eq "\n"; if (/$IGNORE_PATTERN/o) { # Merely delete comments beginning with two hashes. } elsif (/$WHITE_PATTERN/o) { # Stick a single white line before the incoming macro or rule. $spacing = "\n"; am_line_error ($., "blank line following trailing backslash") if $saw_bk; } elsif (/$COMMENT_PATTERN/o) { # Stick comments before the incoming macro or rule. $comment .= $spacing . $_; $spacing = ''; am_line_error ($., "comment following trailing backslash") if $saw_bk; } elsif ($saw_bk) { # continuation of previous line(s) ... if ($was_rule) { $output_trailer .= join ('', @conditional_stack) . $_; $saw_bk = /\\$/; } else { $saw_bk = /\\$/; # Chop newline and backslash if this line is # continued. ensure trailing whitespace exists. chop if $saw_bk; chop if $saw_bk; # decide if to be added to 'contents' ... my $add_it = 0; # assume NO 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 { # we are in a FALSE state if ($cond_true != 1) { $add_it = 1; } } } else { ###prt( "No conditional stack for this macro! lv=[$last_var_name] ". ### "add_it\n" ) if ($debug_on3); $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 ($debug_on3); $add_it = 1; } if ($add_it) { $contents{$last_var_name} .= ' ' unless $contents{$last_var_name} =~ /\s$/; $contents{$last_var_name} .= $_; if (@conditional_stack) { $conditional{$last_var_name} .= "e_cond_val ($_); } prt( "End $last_var_name = [". trim_line($contents{$last_var_name})."]...\n" ) if ( ! $saw_bk && $debug_on3); } else { prt( "Warning: Discarding this [$_] ... CHECK ME!\n" ) if ($debug_on3); } } } elsif (/$IF_PATTERN/o) { if ( defined $configure_cond{$1} ) { ###if ( defined $cfg_defines{$1} ) if ($configure_cond{$1} == 2) { prt( "Found if $1, and condition is TRUE (see cfg_defines) ...\n" ) if ($debug_on3); $cond_true = 1; } else { prt( "Found if $1, but NOT in cfg_defines ...\n" ) if ($debug_on3); $cond_true = 0; } } else { am_line_error ($., "$1 does not appear in AM_CONDITIONAL"); } push (@conditional_stack, "\@" . $1 . "_TRUE\@"); } elsif (/$ELSE_PATTERN/o) { if (! @conditional_stack) { am_line_error ($., "else without if"); } elsif ($conditional_stack[$#conditional_stack] =~ /_FALSE\@$/) { am_line_error ($., "else after else"); } else { $conditional_stack[$#conditional_stack] =~ s/_TRUE\@$/_FALSE\@/; } } elsif (/$ENDIF_PATTERN/o) { if (! @conditional_stack) { am_line_error ($., ": endif without if"); } else { pop @conditional_stack; } $cond_true = 2; # undetermined ... } elsif (/$RULE_PATTERN/o) { # Found a rule. $was_rule = 1; if (defined $contents{$1} && (@conditional_stack ? ! defined $conditional{$1} : defined $conditional{$1})) { am_line_error ($1, "$1 defined both conditionally and unconditionally"); } # Value here doesn't matter; for targets we only note # existence. $contents{$1} = 1; $targets{$1} = 1; my $cond_string = join ('', @conditional_stack); if (@conditional_stack) { if ($conditional{$1}) { check_ambiguous_conditional ($1, $cond_string); $conditional{$1} .= ' '; } else { $conditional{$1} = ''; } $conditional{$1} .= $cond_string . ' 1'; } $content_lines{$1} = $.; $output_trailer .= $comment . $spacing . $cond_string . $_; $comment = $spacing = ''; $saw_bk = /\\$/; # Check the rule for being a suffix rule. If so, store in # a hash. my $source_suffix; my $object_suffix; if (($source_suffix, $object_suffix) = ($1 =~ $SUFFIX_RULE_PATTERN)) { $suffix_rules{$source_suffix} = $object_suffix; prt( "Sources ending in .$source_suffix become .$object_suffix\n" ) if $verbose; $source_suffix_pattern = "(" . join('|', keys %suffix_rules) . ")"; } # FIXME: make sure both suffixes are in SUFFIXES? Or set # SUFFIXES from suffix_rules? } elsif (($is_ok_macro = /$MACRO_PATTERN/o) || /$BOGUS_MACRO_PATTERN/o) { prt( "Found a macro definition. 1[$1] 2[$2] 3[$3] ...\n" ) if ($debug_on3 || $dbg21); $was_rule = 0; $last_var_name = $1; # like say eswig_SOURCES if (defined $contents{$1} && (@conditional_stack ? ! defined $conditional{$1} : defined $conditional{$1})) { am_line_error ($1, "$1 defined both conditionally and unconditionally"); } my $value; if ($3 ne '' && substr ($3, -1) eq "\\") { $value = substr ($3, 0, length ($3) - 1); } else { $value = $3; } my $type = $2; if ($type eq '+') { if (! defined $contents{$last_var_name} && defined $configure_vars{$last_var_name}) { $contents{$last_var_name} = '@' . $last_var_name . '@'; } $contents{$last_var_name} .= ' ' . $value; } else { if ( defined $contents{$last_var_name} ) { if ( @conditional_stack ) { if ( $conditional_stack[$#conditional_stack] =~ /_TRUE\@$/ ) { # we are in the if TRUE state if ($cond_true == 1) { if ($debug_on3) { if ( $contents{$last_var_name} ne $value ) { prt( "NB: [$last_var_name] = [$contents{$last_var_name}]" . " replaced with [$value] (am_file=$am_file line=$.)". (/\\$/ ? "saw_bk" : "end") . "\n" ); } } $contents{$last_var_name} = $value; $content_lines{$last_var_name} = $.; } } else { # we are in the else FALSE state if ($cond_true != 1) { if ($debug_on3) { if ( $contents{$last_var_name} ne $value ) { prt( "NB: [$last_var_name] = [$contents{$last_var_name}]" . " replaced with [$value] (am_file=$am_file line=$.)". (/\\$/ ? "saw_bk" : "end") . "\n" ); } } $contents{$last_var_name} = $value; $content_lines{$last_var_name} = $.; } } } } else { prt( "First setting [$last_var_name] = [$value] " . "(am_file=$am_file line=$.) ". (/\\$/ ? "saw_bk" : "end") . "\n" ) if ($debug_on3); $contents{$last_var_name} = $value; # The first assignment to a macro sets the line # number. Ideally I suppose we would associate line # numbers with random bits of text. $content_lines{$last_var_name} = $.; } } my $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) { $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, "e_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 . ' ' . "e_cond_val ($val)); } } # FIXME: this doesn't always work correctly; it will group # all comments for a given variable, no matter where # defined. $am_vars{$last_var_name} = $comment . $spacing; $def_type{$last_var_name} = ($type eq ':') ? ':' : ''; push (@var_list, $last_var_name); $comment = $spacing = ''; $saw_bk = /\\$/; # Error if bogus. am_line_error ($., "bad macro name \`$last_var_name'") if ! $is_ok_macro; } elsif (/$INCLUDE_PATTERN/o) { $incfile = $1; $path = $incfile; if ($path =~ s/^\$\(top_srcdir\)\///) { push (@include_stack, "\$\(top_srcdir\)/$path"); } else { $path =~ s/\$\(srcdir\)\///; push (@include_stack, "\$\(srcdir\)/$path"); $path = $relat_dir . "/" . $path; } if (! -f $path) { $path = $root_dir . $incfile; } read_am_file ($path); } else { # This isn't an error; it is probably a continued rule. # In fact, this is what we assume. $was_rule = 1; $output_trailer .= ($comment . $spacing . join ('', @conditional_stack) . $_); $comment = $spacing = ''; $saw_bk = /\\$/; } $_ = ; } close(AM_FILE); $output_trailer .= $comment; am_error ("unterminated conditionals: " . join (' ', @conditional_stack)) if (@conditional_stack); } 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". $relat_dir = ''; # This maps the source extension of a suffix rule to its # corresponding output extension. %suffix_rules = (); @am_source_list = (); # list of sources from ONE Makefile.am } # 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; } # this function seems MISSING # if (&conditional_same ($vcond, $cond_string)) sub conditional_same { my ($cond, $when) = @_; if ($when eq $cond) { return 1; } return 0; } # 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 am_error { my $msg = shift; pgm_exit(1,"$msg\n" ); } sub am_line_error { my ($symbol, @args) = @_; prt( "am_line_error: am_file=[$am_file] sym=[$symbol] arg0=[$args[0]] ...\n" ) if ($debug_on3); if ($symbol && "$symbol" ne '-1') { my ($file) = "${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"; $exit_status = 1; } else { am_error (@args); } } sub generate_dsw { my $name = shift; ###my $dsw_name = $root_dir . $name . '.dsw'; my $dsw_name = get_dsw_name($name); prt( "Creating $dsw_name ... " ); show_rename( $dsw_name ); open(DSW, ">$dsw_name") || pgm_exit(1,"ERROR: Can't create $dsw_name: $!\n" ); print DSW <\n"; print DSW < {{{ }}} Package=<4> {{{ }}} EOF foreach my $p (@extra_projects) { print DSW "###############################################################################\n\n"; my ($dsp,$name) = split ',', $p; prt( "Project $name=$dsp\n" ) if $verbose; print DSW "Project: \"$name\"=\"$dsp\" - Package Owner=<4>\n\n"; print DSW < {{{ }}} Package=<4> {{{ }}} EOF } print DSW < {{{ }}} Package=<3> {{{ }}} ############################################################################### EOF close(DSW); } 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 show_rename { my ($fil) = shift; my $res = rename_2_old_bak( $fil ); if ($res == 0) { prt( "NEW FILE" ); } elsif ($res == 1 ) { prt( "RENAMED current to OLD" ); } elsif ($res == 2 ) { prt( "RENAMED current to BAK" ); } else { prt( "RENAMED current to BAK, deleting previous" ); } prt("\n"); } sub console_app_dsp_init { my $name = shift; ###my $dsp_name = $root_dir . $name . '.dsp'; my $dsp_name = get_dsp_name($name); prt( "Creating console app type $dsp_name ... " ); show_rename( $dsp_name ); open(DSP, ">$dsp_name") || pgm_exit(1,"ERROR: Can't create $dsp_name: $!\n" ); print DSP expand_here(< # 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 /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 = shift; ###my $dsp_name = $root_dir . $name . '.dsp'; my $dsp_name = get_dsp_name($name); prt( "Creating static library type $dsp_name ... " ); show_rename( $dsp_name ); open(DSP, ">$dsp_name") || pgm_exit(1,"ERROR: Can't create $dsp_name: $!\n" ); print DSP expand_here(< # 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 /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" EOF close(DSP); } sub dsp_add_source_rule { my ($fh,$dsp_name,$group,$file,$dup) = @_; my ($ff, $nm, $target, $ext, $fromdir, $rp); print $fh "# Begin Source File\n"; print $fh "\n"; $ff = $root_dir . $file; $ff = fix_rel_path($ff); ($nm, $target, $ext) = fileparse( $ff, qr/\.[^.]*/ ); $fromdir = $build_dir; ###$rp = get_relative_path($target, $fromdir); $rp = get_rel_dos_path($target, $fromdir); $rp .= $nm . $ext; prt( "ADDING SOURCE: $rp ($dsp_name, $group, $dup) $ff\n" ) if ($dbg25); if ($use_build_dir) { print $fh "SOURCE=$rp\n"; } else { print $fh "SOURCE=$file\n"; } if ($add_groups) { print $fh "\n"; print $fh "!IF \"\$(CFG)\" == \"$dsp_name - Win32 Release\"\n"; print $fh "\n"; print $fh "# PROP Intermediate_Dir \"Release\\$group\"\n"; print $fh "# PROP Exclude_From_Build 1\n" if exclude_file($file); print $fh "\n"; print $fh "!ELSEIF \"\$(CFG)\" == \"$dsp_name - Win32 Debug\"\n"; print $fh "\n"; print $fh "# PROP Intermediate_Dir \"Debug\\$group\"\n"; print $fh "# PROP Exclude_From_Build 1\n" if exclude_file($file); print $fh "\n"; print $fh "!ENDIF \n"; print $fh "\n"; } elsif ($dup) { add_dupes_dir( \*$fh, $dsp_name ); } print $fh "# End Source File\n"; } sub is_in_list { my ($itm, @lst) = @_; foreach my $fnd (@lst) { if ($fnd eq $itm) { return 1; } } return 0; } # have decoded a Makefile.am file, and extracted a set of sources # This is like in a SLN file when there is a 'project name', and a 'vcproj file' for it # ===================================================================================== sub show_am_sources { my $scnt = scalar @am_source_list; if (!$scnt) { prt( "Got NO sources from Makefile.am ... [$am_file]" ); return; } prt( "Got $scnt sources from Makefile.am ... " ); my @groups = (); my ($src, @bits, $group, $file, $gcnt, $type, $csrccnt, $grpname); my ($nm, $dir, $ext); foreach $src (@am_source_list) { @bits = split( /\|/, $src ); # get file title, name and group $group = $bits[0]; $file = $bits[1]; push(@groups, $group) if (!is_in_list( $group, @groups )); ###prt( "$src\n" ); } $gcnt = scalar @groups; prt( "in $gcnt group". (($gcnt > 1) ? "s" : "") ." ...\n" ); if ($gcnt) { foreach $group (@groups) { if ($group =~ /^lib_(.+)/i) { $grpname = $1; # get the PROJECT NAME $type = 'Library'; } else { $type = 'Application'; $grpname = $group; } $csrccnt = 0; foreach $src (@am_source_list) { @bits = split( /\|/, $src ); # get file group, pathname, title if ($group eq $bits[0]) { $file = $bits[1]; ($nm, $dir, $ext) = fileparse( $file, qr/\.[^.]*/ ); if (is_c_source_ext(substr($ext,1))) { $csrccnt++; } } } prt( "Group = $group ($type $grpname) C src count $csrccnt ...\n" ); foreach $src (@am_source_list) { @bits = split( /\|/, $src ); # get file group, pathname, title if ($group eq $bits[0]) { $file = $bits[1]; ($nm, $dir, $ext) = fileparse( $file, qr/\.[^.]*/ ); if (is_c_source_ext(substr($ext,1))) { prt( "File: C/C++ $dir - $nm - $ext\n" ); } } } foreach $src (@am_source_list) { @bits = split( /\|/, $src ); # get file group, pathname, title if ($group eq $bits[0]) { $file = $bits[1]; ($nm, $dir, $ext) = fileparse( $file, qr/\.[^.]*/ ); if (!is_c_source_ext(substr($ext,1))) { prt( "File: H/++ $dir - $nm - $ext\n" ); } } } } } } # was sub dsp_add_group sub process_am_file { my ($dsp_name,$makefile) = @_; my $base_dir = './'; ###my $dsp_file = $root_dir . $dsp_name .'.dsp'; my $dsp_file = get_dsp_name($dsp_name); my ($mfam); $mfam = $makefile . '.am'; if ( -f $mfam ) { prt( "Processing 1 [$mfam] ...\n" ) if ($verbose2 || $dbg18); } else { $mfam = $root_dir . $makefile . '.am'; prt( "Processing 2 [$mfam] ...\n" ) if ($verbose2 || $dbg18); } ######################################################################################### initialize_per_input(); # reset MAKEFILE parameters my $relative_dir = loc_dir_name($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 read_main_am_file($mfam); # preview the 'contents' to find 'group' # use 'noinst_LIBRARIES' macro foreach $key (keys %contents) { if ($key eq 'noinst_LIBRARIES') { @files = split(' ', $contents{$key}); foreach $file (@files) { if ($file =~ /^lib([\w-]+)\.a/) { $group = 'Lib_' . $1; prt( "Group set to [$group] ...\n" ) if ($debug_on3 || $dbg27); last; } } } } # now extract 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/) { $group = 'Lib_' . $1; @files = split(' ', $contents{$key}); foreach (@files) { my $src_dir = $base_dir . $relative_dir . '/'; $src_dir =~ s/\//\\/g; # fixup DOS path separators if (/^\$\(([^\)]*)\)$/) { # Found a variable. my $varname = $1; prt( "Expanding variable $varname ...\n" ) if ($debug_on3 || $dbg27); foreach (split(' ', $contents{$varname})) { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); } prt( "Done expanding variable $varname ...\n" ) if ($debug_on3); } else { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); } } } #elsif ($key =~ /(.*)_SOURCES/) { elsif ($key eq "fgfs_SOURCES") { $group = 'main'; @files = split(' ', $contents{$key}); foreach $fi (@files) { my $src_dir = $base_dir . $relative_dir . '/'; $src_dir =~ s/\//\\/g; # fixup DOS path separators $file = $src_dir . $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) { $ext = file_extension($fi); $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 $verbose2; } elsif (is_h_source_ext($ext)) { push(@msvc_h_extra, $file); prt( "Added [$file] to H EXTRA list\n" ) if $verbose2; } else { push(@msvc_o_extra, $file); prt( "Added [$file] to other EXTRA list\n" ) if $verbose2; } } } 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) { $ext = file_extension($fi); 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 ); } } } else { # key is NOT ( Lib(.*)_a_SOURCES fgfs_SOURCES ) # and NOT (($key eq 'EXTRA_DIST')||($key eq 'fgjs_SOURCES')) { # and NOT ($key eq 'noinst_HEADERS') if ($key =~ /(\w+)_SOURCES/) { my $prog = $1; # get the PROGRAM name $file = trim_all($contents{$key}); @files = split(/\s/, $file); foreach $fi (@files) { $ext = file_extension($fi); if (is_c_source_ext($ext)) { # if a C/C++ source $file = $base_dir . $relative_dir . '/' . $fi; $file =~ s/\//\\/g; # use DOS path sep $dupe = add_2_source_list( $file, $prog ); } } } } } } show_am_sources(); prt( "Done $mfam ...\n" ) if ($verbose2 || $dbg18); } sub dsp_finish { my $dsp_name = shift; ###my $dsp_file = $root_dir . $dsp_name . '.dsp'; my $dsp_file = get_dsp_name($dsp_name); open(DSP, ">>$dsp_file") || pgm_exit(1,"ERROR: Can't append to $dsp_file: $!\n" ); foreach my $r (@extra_sources) { print DSP "# Begin Source File\n\n"; print DSP "$r\n"; print DSP "# End Source File\n"; } print DSP "# End Target\n"; print DSP "# End Project\n"; close(DSP); } # Return directory name of file. sub loc_dir_name { my ($file) = @_; my ($name,$dir) = fileparse($file); $dir = $cwdir if ($dir =~ /^\.(\\|\/)$/); return $dir; } sub add_2_used_libs { my ($fil,$in) = @_; if (exists( $used_lib_paths{$in} ) ) { my @incs = split(/\|/ , $used_lib_paths{$in}); my $got = 0; foreach my $i (@incs) { if ($i eq $fil) { $got = 1; last; } } if ( ! $got ) { $used_lib_paths{$in} .= '|'.$fil; # add new } } else { $used_lib_paths{$in} = $fil; # set first } } sub check_lib_paths { my $fil = shift; my $inc = ''; my $ff = ''; my $finc = ''; my $fincr = ''; my $fincd = ''; my $found1 = 0; my $found2 = 0; my $found3 = 0; foreach $inc (@msvc_libs_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; if( -f $ff ) { $finc = $inc; $found1 = 1; last; } } foreach $inc (@msvc_rlibs_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; if( -f $ff ) { $fincr = $inc; $found2 = 1; last; } } foreach $inc (@msvc_dlibs_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; if( -f $ff ) { $fincd = $inc; $found3 = 1; last; } } if( $found1 || $found2 || $found3 ) { prt( "Found [$fil] in [$finc] [$ff] ...\n" ) if ($verbose2 && $found1); prt( "Found [$fil] in [$fincr] [$ff] ...\n" ) if ($verbose2 && $found2); prt( "Found [$fil] in [$fincd] [$ff] ...\n" ) if ($verbose2 && $found3); add_2_used_libs( $fil, $finc ) if $found1; add_2_used_libs( $fil, $fincr ) if $found2; add_2_used_libs( $fil, $fincd ) if $found3; } else { prt( "WARNING: Unable to locate $fil ...\n" ) if $verbose2; } return ($found1 + $found2 + $found3); } sub check_inc_paths { my $fil = shift; my $inc = ''; my $ff = ''; my $found = 0; if( ! $found ) { foreach $inc (@msvc_inc_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; ### print "Checking for $fil in $ff ...\n" if $verbose9; if( -f $ff ) { if (exists( $used_inc_paths{$inc} ) ) { my @incs = split(/\|/ , $used_inc_paths{$inc}); my $got = 0; foreach my $i (@incs) { if ($i eq $fil) { $got = 1; last; } } if ( ! $got ) { $used_inc_paths{$inc} .= '|'.$fil; # add new } } else { $used_inc_paths{$inc} = $fil; # set first } $found = 1; last; } } } if( $found ) { prt( "Found $fil in $inc [$ff] ...\n" ) if $verbose2; } else { prt( "WARNING: Unable to locate $fil ...\n" ) if $verbose2; } return $found; } sub show_lib_found { my (@arr) = @_; foreach my $in (@arr) { if (exists( $used_lib_paths{$in} ) ) { my @ip = split(/\|/, $used_lib_paths{$in}); prt( "On path [$root_dir][$in] found ".scalar @ip." items ...\n" ); my $cntr = 0; $in .= '\\' if !($in =~ /(\\|\/)$/); foreach my $f (@ip) { $cntr++; prt( "$cntr ".$root_dir.$in.$f."\n" ); } } else { prt( "Warning: Found nothing on [$root_dir][$in] ...\n" ); } } } sub check_includes { my $fil = ''; my $ff = ''; my $cnt1 = 0; my $cnt2 = 0; my @missed = (); my @missed2 = (); my $inc = ''; my @incpath = (); $cnt1 = scalar @msvc_dlibs_list + scalar @msvc_rlibs_list + scalar @msvc_libs_list; prt( "\nCheck 1: each $cnt1 additional library, in each library include path ...\n" ); foreach $fil (@msvc_dlibs_list) { if( check_lib_paths( $fil ) == 0 ) { push(@missed, $fil); } } foreach $fil (@msvc_rlibs_list) { if( check_lib_paths( $fil ) == 0 ) { push(@missed, $fil); } } foreach $fil (@msvc_libs_list) { if( check_lib_paths( $fil ) == 0 ) { push(@missed, $fil); } } show_lib_found(@msvc_libs_paths); show_lib_found(@msvc_rlibs_paths); show_lib_found(@msvc_dlibs_paths); if( @missed ) { prt( "WARNING: Missed ". join(' ',@missed) . ".\n" ); prt( "Check 'add_lib' and 'lib_path' in $src_cfg ...\n" ); } else { prt( "Appears no libraries are is missing ...\n" ); } prt( "Done 1: each $cnt1 additional library, in each library include path ...\n" ); # check for a known set of INCLUDE (or source) files $cnt2 = scalar @test_headers; prt( "\nCheck 2: each of $cnt2 test headers, in each include path ...\n" ); foreach $fil (@test_headers) { if( check_inc_paths( $fil ) == 0 ) { push(@missed2, $fil); } } foreach $inc (@msvc_inc_paths) { if (exists( $used_inc_paths{$inc} ) ) { @incpath = split(/\|/, $used_inc_paths{$inc}); prt( "On path [$root_dir][$inc] found ".scalar @incpath." items ...\n" ); my $cntr = 0; foreach $fil (@incpath) { $cntr++; if ( ! ($inc =~ /(\\|\/)$/) ) { $inc .= '\\'; } prt( "$cntr ".$root_dir.$inc.$fil."\n" ); } } else { prt( "Warning: Found nothing on [$root_dir][$inc] ...\n" ); } } if( @missed2 ) { prt( "WARNING: Missed ". join(' ',@missed2) . ".\n" ); prt( "Check 'include_path' in $src_cfg ...\n" ); } else { prt( "Appears no test sources, headers are missing ...\n" ); } prt( "Done checking $cnt1 libraries, and $cnt2 test includes ...\n" ); ## #V8 check_vc8_proj(); # NO RETURN FROM HERE pgm_exit(0,"End check of libraries and include files ... aborting ...\n" ); } # some simple utility functions # ============================= sub is_c_source_ext { my $fil = shift; my $fe = lc($fil); return 1 if (($fe eq 'c')||($fe eq 'cxx')||($fe eq 'cpp')); return 1 if (($fe eq '.c')||($fe eq '.cxx')||($fe eq '.cpp')); return 0; } sub is_h_source_ext { my $fil = shift; my $fe = lc($fil); return 1 if (($fe eq 'h')||($fe eq 'hxx')||($fe eq 'hpp')); return 1 if (($fe eq '.h')||($fe eq '.hxx')||($fe eq '.hpp')); return 0; } sub add_2_source_list { my ($fil, $grp) = @_; $fil =~ s/\\\\/\\/; my ($ft,$dr,$fe) = fileparse($fil, qr/\.[^.]*/); #my $fe = file_extension($fil); #my $ft = lc(file_title($fil)); my $src = ($grp . '|' . $fil . '|' . $ft); my $ret = 0; push(@am_source_list, $src); ###if (($fe eq 'c')||($fe eq 'cxx')||($fe eq 'cpp')) { if ( is_c_source_ext($fe) ) { prt( "Add $src to C list\n" ) if ($verbose2 || $dbg27); 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); } else { prt( "Add $src to H list\n" ) if ($verbose2 || $dbg27); push(@msvc_h_files, $src); } return $ret; } sub add_dupes_dir { my ($fh, $pack) = @_; print $fh "\n"; print $fh "!IF \"\$(CFG)\" == \"$pack - Win32 Release\"\n"; print $fh "\n"; print $fh "# PROP Intermediate_Dir \"Release\\Dupes\"\n"; print $fh "\n"; print $fh "!ELSEIF \"\$(CFG)\" == \"$pack - Win32 Debug\"\n"; print $fh "\n"; print $fh "# PROP Intermediate_Dir \"Debug\\Dupes\"\n"; print $fh "\n"; print $fh "!ENDIF\n"; print $fh "\n"; } ###################################### sub write_new_dsp { my $src_cnt = scalar @msvc_c_files; my $new_pack = $dsp_package; my $src; ###my $dsp_file = $root_dir . $new_pack .'.dsp'; my $dsp_file = get_dsp_name($new_pack); my @bits = (); my @done = (); my $group = ''; my $pgrp = ''; my $tit = ''; my $isdupe = 0; if ($src_cnt == 0) { $err_msg = "WARNING: There are NO SOURCES in \@msvc_c_files, so no DSP/DSW generated!\n"; prtw($err_msg); return; } if ($static_lib) { static_lib_dsp_init($new_pack); } else { console_app_dsp_init($new_pack); } open(DSP, ">>$dsp_file") || pgm_exit(1,"ERROR: Can't append to $dsp_file: $!\n" ); if ( ! $add_groups) { print DSP "# Begin Group \"Source Files\"\n"; print DSP "\n"; print DSP "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n"; } foreach $src (@msvc_c_files) { prt( "Processing $src from array ...\n" ) if $verbose2; @bits = split( /\|/, $src ); # get file title, name and group $group = 'Lib_' . $bits[0]; $tit = $bits[2]; $isdupe = 0; if ($add_groups && ($group ne $pgrp)) { print DSP "# Begin Group \"$group\"\n"; print DSP "\n"; print DSP "# PROP Default_Filter \"\"\n"; } else { # not adding groups, check duplicate names foreach my $tt (@done) { if( $tt eq $tit ) { $isdupe = 1; last; } } } dsp_add_source_rule(\*DSP, $new_pack, $group, $bits[1], $isdupe); if ( !$add_groups && $isdupe) { prt( "Processed a DUPLICATE $tit from array ...\n" ) if $verbose2; prt( "Bits = ".$bits[0]."|".$bits[1].'|'.$bits[2]. " ...\n" ) if $verbose2; } push(@done, $tit); if ($add_groups && ($group ne $pgrp)) { print DSP "# End Group\n"; } $pgrp = $group; } if ( !$add_groups) { print DSP "# End Group\n"; } # just the HEADER files print DSP "# Begin Group \"Header Files\"\n"; print DSP "\n"; print DSP "# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n"; my $savgrp = $add_groups; $add_groups = 0; foreach $src (@msvc_h_files) { @bits = split( /\|/, $src ); # get file title, name and group $group = 'Lib_' . $bits[2]; dsp_add_source_rule(\*DSP, $new_pack, $group, $bits[1], 0); } print DSP "# End Group\n"; close(DSP); $add_groups = $savgrp; dsp_finish($new_pack); generate_dsw($new_pack); prt( "Done temp.".$new_pack." DSP and DSW files ...\n" ); } sub trim_line { my ($l) = shift; chomp $l; $l =~ s/\r$//; # and remove CR, if present $l =~ s/\t/ /g; $l =~ s/\s\s/ /g while ($l =~ /\s\s/); #$l = substr($l,1) while ($l =~ /^\s/); #$l = substr($l,0,length($l)-1) while (($l =~ /\s$/)&&(length($l))); for ($l) { s/^\s+//; s/\s+$//; } return $l; } # RENAME A FILE TO .OLD, or .BAK # 0 - do nothing if file does not exist. # 1 - rename to .OLD if .OLD does NOT exist # 2 - rename to .BAK, if .OLD already exists, # 3 - deleting any previous .BAK ... sub rename_2_old_bak { my ($fil) = shift; my $ret = 0; # assume NO SUCH FILE if ( -f $fil ) { # is there? my ($nm,$dir,$ext) = fileparse( $fil, qr/\.[^.]*/ ); my $nmbo = $dir . $nm . '.old'; $ret = 1; # assume renaming to OLD if ( -f $nmbo) { # does OLD exist $ret = 2; # yes - rename to BAK $nmbo = $dir . $nm . '.bak'; if ( -f $nmbo ) { $ret = 3; unlink $nmbo; } } rename $fil, $nmbo; } return $ret; } ###################################################################### ## MAINLY DEBUG ONLY THINGS ###################################################################### ##################################################### ## prt_list ## Debug output of line list, with some rough ## indenting ... ##################################################### sub prt_list { my (@list) = @_; my $ind = ''; foreach my $line (@list) { if ($line =~ /^/) { # end xml same line } elsif ($line =~ /^<\//) { $ind = substr($ind, 1) if (length($ind)); } else { # $ind .= ' '; } } prt( $ind.$line."\n" ); if ($line =~ /^/) { # end xml same line } elsif ($line =~ /^<\//) { # $ind = substr($ind, 1) if (length($ind)); } else { $ind .= ' '; } } } } ## my %config_ac_macros = (); sub do_macro_sub2 { my ($item) = shift; ###prt( "Checking substitution for [$item] ...\n" ) if ($dbg27); if (defined $config_ac_macros{$item}) { # if it is IN the MACROS my $ritem = $config_ac_macros{$item}; # extract the substitute value ###prt( "Found: returning [$ritem] ...\n" ) if ($dbg27); return $ritem; } return $item; } sub do_macro_sub { my ($item) = shift; if ($item =~ /^\$/) { my $msub = substr($item,1); # remove leading '$' my $ritem = do_macro_sub2($msub); if ($ritem ne $msub) { return $ritem; } } return $item; } sub prtw { my ($txt) = shift; $txt =~ s/\n$//; push(@warnings,$txt); prt("$txt\n"); } sub get_root_name { my ($pn) = shift; my $rn = 'temp.'.$pn; return $rn; } sub get_dsp_name { my ($pn) = shift; my $dsp = get_root_name($pn).'.dsp'; return $dsp; } sub get_dsw_name { my ($pn) = shift; my $dsp = get_root_name($pn).'.dsw'; return $dsp; } sub fix_rel_path { my ($path) = shift; $path = path_u2d($path); # ENSURE DOS PATH SEPARATOR (in relative.pl) my @a = split(/\\/, $path); my $npath = ''; 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=$path\n" ); } } else { push(@na,$p); } } foreach my $pt (@na) { $npath .= "\\" if length($npath); $npath .= $pt; } return $npath; } # redone using File::Basename; sub file_extension { my $fil = shift; my ($nm, $dir, $ext) = fileparse( $fil, qr/\.[^.]*/ ); $ext = substr($ext,1) if ($ext =~ /^\./); return $ext; } sub file_title { my $fil = shift; my ($nm, $dir, $ext) = fileparse( $fil, qr/\.[^.]*/ ); return $nm; } # debug items sub set_all_debug { $debug_on = 1; $debug_on3 = 1; $sw_dbg = 1; $dbg10 = 1; # show EACH line in configure.ac parse $dbg11 = 1; # show "Split to $vlen components ... $dbg12a = 1; # show prt( "Adding $input [$ff] to make_input_list ... - items added to @make_input_list $dbg12b = 1; # show items added to @other_input_list $dbg13 = 1; # show ac_output_line information ... $dbg14 = 1; # prt( "Variable $key=$nval\n" $dbg15 = 1; # prt( "Copying " . scalar @make_input_list . " make_input_list to input_files.\n" ) if ($verbose2 || $dbg15); $dbg16 = 1; # prt( "Substitute $key=$nval\n" ) if ((($orgkey ne $key)||($orgnval ne $nval)) && $dbg16); $dbg17 = 1; # prt( "\nProcessing [$am_file] from input_files array ...\n" ) if ($verbose2 || $dbg17); $dbg18 = 1; # prt( "process_am_file: using dsp_name=$dsp_file, and makefile=$makefile ...\n" ) if ($verbose2 || $dbg18); $dbg19 = 1; # prt( "$pack: reading $am_file\n" ) if ($verbose || $dbg19); $dbg20 = 1; # prt( "$. [$aml]\n" ) if ($debug_on3 || /$dbgnn/); $dbg21 = 1; # prt( "Found a macro definition. 1[$1] 2[$2] 3[$3] ...\n" ) if ($debug_on3 || /$dbgnn/); $dbg22 = 1; # show_contents() if (/$dbgnn/); $dbg23 = 1; # show contents of %config_ac_macros $dbg24 = 1; # prt( "$. Should JOIN lines? - [$cline]\n" ) if (/$dbgnn/); $dbg25 = 1; # prt( "ADDING SOURCE: $file ($dsp_name, $group, $dup)\n" ) if (/$dbgnn/); $dbg26 = 1; # prt( "$. Got AC_INIT = [$1]\n" ) if (/$dbgnn/); $load_log = 1; } ########################################################## ### MAIN ### # set_all_debug(); # turn ON ALL noise #$debug_on3 = 1; parse_arguments(@ARGV); # Read project configuration file, IF ANY, else warning ... read_am2dsp_rc($src_cfg); scan_configure(); # check for configure.ac, configure.in, even configure.ac.in if ( ! @input_files ) { prt( "$pack: no input_files, so no 'Makefile.am' found or specified\n" ); $exit_status = 1; } foreach $am_file (@input_files) { if (exclude_dir($am_file)) { prt( "NO Process of [$am_file] - in excluded directory!" ); } else { prt( "Processing [$am_file].am from input_files array ...\n" ); # if ($verbose2 || $dbg17); process_am_file($dsp_package, $am_file); } } if ($do_check) { check_includes(); } write_new_dsp(); # NEW DSP separating source and headers pgm_exit(0,""); # end of process ########################################################## # =================================================== # # TODO: option to specify static library or console app. # sub give_little_help { prt( "am2dsp".$vers.": Version 0.8.1 September, 2010. 13/09/2010\n"); prt( " Suspended this script for now. See amsrcs04.pl for fuller implementation.\n"); prt("Usage: $pgmname [options] [file] or [directory]\n"); prt("Options:\n"); prt(" --help (or -h, -?) = This brief help, and exit 0\n" ); prt(" --verbose (or -v) = Sets verbose mode. (v2,v3 for MORE, -dbg for ALL)\n" ); prt(" --package name - Set the DSP package name (default = $dsp_package)\n" ); prt(" --lib (or -l) - To create static library (Default is console app.)\n" ); # prt( "--groups (-g) - Output source into 'group' folders, as original!\n" ); prt(" --dir path (-d) - Establish input path for source, and the $def_cfg.\n" ); prt(" --check (or -c) - Check libraries, and some known include files, and exit.\n" ); prt(" --cfg path\\file - Use a specific configuration file, if not with source.\n" ); prt(" --load_log (-ll) - Load log file at end of processing.\n"); prt("Purpose:\n"); prt(" The original purpose was to process the GNU autotool build files, configure.ac, and each\n"); prt(" Makefile.am indicated by the AC_OUTPUT(...) macro of SimGear and Flightgear sources, with an\n"); prt(" aim of producing an up-to-date MSVC DSW/DSP build file set. While attempts were made over the\n"); prt(" years to broaden the scope, none the less, it remains quite 'specialized' for SG and FG.\n"); prt(" There are subseqent scripts, amsrcs.pl, am2list.pl, ... etc, which work harder at being fully\n"); prt(" generalised for other sources.\n"); prt("Notes:\n"); prt(" The --cfg path\\file MUST be after the --dir path, if used.\n" ); prt(" Any other option beginning with '-' will abort, with a complaint ...\n" ); prt(" If a file given, assumed to be the leading/primary Makefile.am\n"); prt(" If a directory given, assumed to be the source of the initial Makefile.am\n"); prt(" If no input, the current work directory assume the source of the initial Makefile.am\n"); pgm_exit(0,"Help exit 0"); } sub set_input_dir { my $cfg = shift; if ( !(($cfg =~ /\/$/) || ($cfg =~ /\\$/)) ) { $cfg .= '\\'; } my $fil = $cfg . $def_cfg; $src_cfg = $fil; $root_dir = $cfg; prt( "Using root path [$root_dir] ...\n" ); } # Ensure argument exists, or die. sub require_argument { my ($arg, @arglist) = @_; pgm_exit(1,"ERROR:$pack: no argument given for option '$arg'\n" ) if ! @arglist; } sub parse_arguments { my @av = @_; my ($arg,$sarg); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i) || ($sarg eq '?')) { give_little_help(); # show help and exit } elsif ($sarg =~ /^v/i) { # deal with verbosity eq '--verbose' || $arg eq '-v') if ($sarg =~ /^v2$/i ) { $verbose2 = 1; } elsif ($sarg =~ /^v3$/i) { $verbose3 = 1; } else { $verbose++; } } elsif ($sarg =~ /^p/i) { # arg eq '--package' || $arg eq '-p') require_argument(@av); shift @av; $dsp_package = $av[0]; prt("Set DSP package name to [$dsp_package]\n"); } elsif (($sarg =~ /^lib$/i)||($sarg =~ /^l$/i)) { # Create a static library $static_lib = 1; } elsif (($sarg =~ /^dir$/i)||($sarg =~ /^d$/i)) { require_argument(@av); shift @av; set_input_dir($av[0]); } elsif (($sarg =~ /^check$/i) || ($sarg =~ /^c$/i)) { $do_check = 1; # perform check and exit } elsif ($sarg =~ /^cfg$/i) { require_argument(@av); shift @av; $src_cfg = $av[0]; } elsif (($sarg =~ /^load_log$/i)||($sarg =~ /^ll$/i)) { $load_log = 1; } elsif ($sarg =~ /^dbg$/i ) { $sw_dbg = 1; $verbose = 1; $verbose2 = 1; $verbose3 = 1; } else { pgm_exit(1,"ERROR: Unrecognised option [$arg]\n Try --help or -? for some information.\n" ); } } else { if (-f $arg) { ($sarg,$root_dir) = fileparse($arg); } elsif (-d $arg) { $root_dir = $arg; } else { pgm_exit(1,"ERROR: Unrecognised item [$arg]\n Is NOT file nor directory!\n" ); } prt("Set ROOT directory to [$root_dir]\n"); } shift @av; } # THIS IS ESSENTIALLY ONLY FOR DEBUG - so no command input works for a trial ####################################################################################### if ($use_def) { my $ff = $root_dir; $ff .= "\\" if (length($ff) && !( substr($ff,-1,1) =~ /(\\|\/)/)); $ff .= 'configure.ac'; if (! -f $ff) { prt( "Under DEBUG, switch root from [$root_dir] to [$def_root] ...\n" ); $root_dir = $def_root; ###$src_cfg = $root_dir . $def_cfg; } if ( !( -f $src_cfg) ) { $err_msg = "WARNING: Unable to locate file [$src_cfg] ... "; if ( $use_cwd_cfg && ( -f $def_cfg)) { $err_msg .= "Using file [$def_cfg], in [".getcwd()."], in its place ...\n"; $src_cfg = $def_cfg; } else { $err_msg .= "Check input, and/or folder ... \n"; } prtw($err_msg); } # TRY TO DETERMINE TYPE FROM ROOT FOLDER if ($root_dir =~ /FlightGear/) { if ($static_lib) { prtw("WARNING: Setting variable \$static_lib to OFF- root=$root_dir\n"); $static_lib = 0; } } elsif ($root_dir =~ /SimGear/) { if (!$static_lib) { prtw("WARNING: Setting variable \$static_lib to ON - root=$root_dir\n"); $static_lib = 1; } } } ####################################################################################### if (length($root_dir) == 0) { $root_dir = $cwdir; prt("Set ROOT directory to CURRENT [$root_dir]\n"); } $root_dir .= "\\" if ( !($root_dir =~ /(\\|\/)$/) ); if (length($build_dir) == 0) { $build_dir = $root_dir; # initially make them the SAME if ($use_def && length($def_build)) { $build_dir = $def_build; } } } # eof - am2dsp7.pl