Generated: Tue Feb 2 17:54:18 2010 from am2dsp4.pl 2006/04/16 44.6 KB.
#!/usr/bin/perl -w eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; use strict; use Cwd; my $VERSION = "0.4"; my $PACKAGE = "am2dsp4"; # 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]*([^)]+)"; # 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 = (); my %conditional = (); # This holds our (eventual) exit status. We don't actually exit until # we have processed all input files. 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 $relative_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 = (); # new variables my $verbose2 = 0; my $msvc_dlibs = ""; my $msvc_rlibs = ""; my $in_debug = 0; my $in_release = 0; my $do_check = 0; my $def_cfg = "am2dsp4.cfg"; my $src_cfg = $def_cfg; my $root_dir = ''; 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' ); 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 # Extracted from AM_INIT_AUTOMAKE(package,version) my $dsp_package = 'FGFS'; my $dsp_version = '0.2'; my $static_lib = 0; my ($LOG); my $outfile = 'templog.txt'; open $LOG, ">$outfile" or die "Unable to open $outfile LOG ...\n"; parse_arguments(@ARGV); # Read project configuration file. # my $rcfile = "am2dsp4.cfg"; # read_am2dsprc($rcfile) if -r $rcfile; read_am2dsprc($src_cfg); if ($do_check) { check_includes(); } scan_configure(); die "$PACKAGE: no input_files, so no 'Makefile.am' found or specified\n" if ! @input_files; if ($static_lib) { static_lib_dsp_init($dsp_package); } else { console_app_dsp_init($dsp_package); } my $am_file; if ( ! $add_groups) { add_group_start($dsp_package); } foreach $am_file (@input_files) { print "Processing [$am_file] from input_files array ...\n" if $verbose2; dsp_add_group($dsp_package, $am_file) if !exclude_dir($am_file); } if ( ! $add_groups) { add_group_end($dsp_package); } dsp_finish($dsp_package); generate_dsw( $dsp_package ); print "Done ".$root_dir.$dsp_package." DSP and DSW files ...\n"; if (uc($dsp_package) ne 'FGFS') { ### write_new_dsp(); # experimental NEW DSP separating source and headers amend_vcproj(); # experimental - amend the VCPROJ files } # end of process sub add_group_start { my $dsp_name = shift; my $dsp_file = $root_dir . $dsp_name . '.dsp'; open(DSP, ">>$dsp_file") || die "Can't append to $dsp_file: $!\n"; print DSP "# Begin Group \"Source Files\"\r\n"; print DSP "\r\n"; print DSP "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;h;hpp;hxx;hm;inl\"\r\n"; close(DSP); } sub add_group_end { my $dsp_name = shift; my $dsp_file = $root_dir . $dsp_name . '.dsp'; open(DSP, ">>$dsp_file") || die "Can't append to $dsp_file: $!\n"; print DSP "# End Group\r\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; } # # TODO: option to specify static library or console app. # sub give_little_help { print "am2dsp4: Just a little help ...\n"; print "--help (or -h, -?) - This brief help!\n"; print "--verbose (or -v) - Sets verbose mode. (-v2 for MORE)\n"; print "--package name - Set the DSP package name (default = $dsp_package)\n"; print "--lib (or -l) - To create static library (Default is console app.)\n"; print "--groups (or -g) - Output source into 'group' folders, as original!\n"; print "--dir path - Establish input path for source, and the $def_cfg.\n"; print "--check (or -c) - Check libraries, and some known include files, and exit.\n"; print "--cfg path\\file - Use a specific configuration file, if not with source.\n"; print "Note, this --cfg path\\file MUST be after the --dir path, if used.\n"; print "Any other option beginning with '-' will abort, with a complaint ...\n"; die "Any other input - is ignored ...\n"; } sub set_input_dir { my $cfg = shift; if ( !(($cfg =~ /\/$/) || ($cfg =~ /\\$/)) ) { $cfg .= '\\'; } my $fil = $cfg . $def_cfg; $src_cfg = $fil; $root_dir = $cfg; print "Using root path [$root_dir] ...\n"; } sub parse_arguments { my @av = @_; my $arg = ''; while (@av) { $arg = $av[0]; if ($arg eq '--help' || $arg eq '-h' || $arg eq '-?') { give_little_help(); # show help and exit } elsif ($arg eq '--verbose' || $arg eq '-v') { $verbose = 1; } elsif ($arg eq '--package' || $arg eq '-p') { require_argument(@av); shift @av; $dsp_package = $av[0]; } elsif ($arg eq '--lib' || $arg eq '-l') { # Create a static library $static_lib = 1; } elsif ($arg eq '--dir') { require_argument(@av); shift @av; set_input_dir($av[0]); } elsif ($arg eq '--check' || $arg eq '-c') { $do_check = 1; # perform check and exit } elsif ($arg eq '--cfg') { require_argument(@av); shift @av; $src_cfg = $av[0]; } elsif ($arg eq '-v2' ) { $verbose2 = 1; } elsif ($arg eq '--groups' || $arg eq '-g') { $add_groups = 1; # use original 'group' folders ... } elsif ($arg =~ /^-/) { die "am2dsp4: unrecognised option -- '$arg'\nTry --help or -? for some information.\n"; } else { # quietly IGNORE other inputs??? } shift @av; } if ( !( -f $src_cfg) ) { die "ERROR: Unable to locate file [$src_cfg] ... \ncheck input, and/or folder ... aborting ...\n"; } } 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_am2dsprc { my $rc_file = shift; open( RC_FILE, $rc_file ) or die "Can't open $rc_file: $!\n"; my $line; my @cond_stack = (); while (defined($line = <RC_FILE>)) { chomp $line; if ($line =~ s/\\$//) { # continuation line $line .= "%"; $line .= <RC_FILE>; redo unless eof(RC_FILE); } 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 ); print "Excluding file: $f\n" if $verbose; } elsif ($line =~ /include_path\s*=\s*(\S+)/) { $msvc_cflags .= " /I \"$1\""; push(@msvc_inc_paths, $1); } elsif ($line =~ /define\s*=\s*(\S+)/) { $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; print "type=$type, threading=$threads, debug=$debug\n" if $verbose; if ($type =~ "ConsoleApplication") { $static_lib = 0 } elsif ($type =~ "StaticLibrary") { $static_lib = 1 } else { # Invalid type } my $flags = " /ML"; # single threaded. if ($threads =~ /Multithreaded/) { $flags = " /MT"; } elsif ($threads =~ /Singlethreaded/) { $flags = " /ML"; } else { # Invalid threading option. } if ($debug =~ /Debug/) { $flags .= "d"; } $msvc_cflags .= $flags; } elsif ($line =~ /add_source_file\s*=\s*(.*)/) { my $rule; ($rule = $1) =~ s/%/\r\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) { print "Entering DEBUG ...\n" if $verbose2; $in_debug = 1; $in_release = 0; } elsif ($ifcond =~ /Release/io) { print "Entering RELEASE ...\n" if $verbose2; $in_release = 1; $in_debug = 0; } else { print "EEK! Got $ifcond ...\n"; die "Presently ONLY if switch is 'Debug' or 'Release'!\n"; } push (@cond_stack, "\@" . $ifcond . "_TRUE\@"); } elsif ($line =~ /$ELSE_PATTERN/o) { if (! @cond_stack) { die "else without if!\n"; } elsif ($cond_stack[$#cond_stack] =~ /_FALSE\@$/) { die "else after an else!\n"; } else { if ($in_debug) { print "Switch to RELEASE ...\n" if $verbose2; $in_debug = 0; $in_release = 1; } else { print "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) { die "endif without if!\n"; } print "Exit $cond_stack[$#cond_stack] ...\n" if $verbose2; pop (@cond_stack); $in_debug = 0; $in_release = 0; } } # end while close(RC_FILE); } # Ensure argument exists, or die. sub require_argument { my ($arg, @arglist) = @_; die "$PACKAGE: no argument given for option '$arg'\n" if ! @arglist; } sub scan_configure { my $ff = $root_dir . 'configure.ac'; scan_one_configure_file($ff); $ff = $root_dir . 'aclocal.m4'; scan_one_configure_file($ff) if -f $ff; if (! @input_files) { print "Copying " . scalar @make_input_list . " make_input_list to input_files.\n" if $verbose2; @input_files = @make_input_list; if ($verbose2) { foreach $ff (@input_files) { print "$ff\n"; } } %output_files = %make_list; } else { print "input_files has list of " . scalar @input_files . " ...\n" if $verbose2; } } sub scan_one_configure_file { my $filename = shift; open(CONFIGURE, $filename) || die "$PACKAGE: can't open \`$filename': $!\n"; print "$PACKAGE: reading $filename\n" if $verbose; my $in_ac_output = 0; my $ac_output_line = ''; my $ff = ''; while (<CONFIGURE>) { # Remove comments from current line. s/\bdnl\b.*$//; s/\#.*$//; # Skip macro definitions. Otherwise we might be confused into # thinking that a macro that was only defined was actually # used. next if /AC_DEFUN/; # Follow includes. This is a weirdness commonly in use at # Cygnus and hopefully nowhere else. if (/sinclude\((.*)\)/ && -f ($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 = $.; } if ($in_ac_output) { my $closing = 0; if (s/[\]\),].*$//) { $in_ac_output = 0; $closing = 1; } # Look at potential Makefile.am's foreach (split) { # Must skip empty string for Perl 4. next if $_ eq "\\" || $_ eq ''; my ($local,$input,@rest) = split(/:/); if (! $input) { $input = $local; } else { $input =~ s/\.in$//; } $ff = $root_dir . $input . '.am'; if (-f $ff) { printf "Adding $input [$ff] to make_input_list ...\n" if $verbose2; push(@make_input_list, $input); $make_list{$input} = join(':', ($local,@rest)); } else { # 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) { $configure_cond{$1} = 1; } if (/$AM_INIT_AUTOMAKE/o) { $dsp_package = $1; $dsp_version = $2; } } close(CONFIGURE); } sub read_main_am_file { $am_file = shift; read_am_file($am_file); my @topdir = (); foreach (split(/\//, $relative_dir)) { next if $_ eq '.' || $_ eq ''; if ($_ eq '..') { pop @topdir; } else { push(@topdir, '..'); } } @topdir = ('.') if ! @topdir; my $top_builddir = join('/', @topdir); } sub read_am_file { $am_file = shift; open( AM_FILE, $am_file ) or die "Can't open $am_file: $!\n"; print "$PACKAGE: reading $am_file\n" if $verbose; my $saw_bk = 0; my $was_rule = 0; my $spacing = ''; my $comment = ''; my $last_var_name = ''; my $blank = 0; while (<AM_FILE>) { 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 ($_) { $_ .= "\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) { 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; $contents{$last_var_name} .= ' ' unless $contents{$last_var_name} =~ /\s$/; $contents{$last_var_name} .= $_; if (@conditional_stack) { $conditional{$last_var_name} .= "e_cond_val ($_); } } } elsif (/$IF_PATTERN/o) { &am_line_error ($., "$1 does not appear in AM_CONDITIONAL") if (! $configure_cond{$1}); 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; } } 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; print "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) { # Found a macro definition. $was_rule = 0; $last_var_name = $1; 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 { $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) { my ($path) = $1; if ($path =~ s/^\$\(top_srcdir\)\///) { push (@include_stack, "\$\(top_srcdir\)/$path"); } else { $path =~ s/\$\(srcdir\)\///; push (@include_stack, "\$\(srcdir\)/$path"); $path = $relative_dir . "/" . $path; } &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 = /\\$/; } $_ = <AM_FILE>; } 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". $relative_dir = ''; # This maps the source extension of a suffix rule to its # corresponding output extension. %suffix_rules = (); } # 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; } # 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)) { print "$var_name multiply defined in condition"; } } } sub am_error { my $msg = shift; die $msg."\n"; } sub am_line_error { my ($symbol, @args) = @_; 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'; open(DSW, ">$dsw_name") || die "Can't create $dsw_name: $!\n"; print "Creating $dsw_name\n" if $verbose; print DSW <<"EOF"; Microsoft Developer Studio Workspace File, Format Version 6.00\r # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r \r ###############################################################################\r \r EOF print DSW 'Project: ', "\"$name\"=\".\\", $name, ".dsp\" - Package Owner=<4>\r\n"; print DSW <<"EOF"; \r Package=<5>\r {{{\r }}}\r \r Package=<4>\r {{{\r }}}\r \r EOF foreach my $p (@extra_projects) { print DSW "###############################################################################\r\n\r\n"; my ($dsp,$name) = split ',', $p; print "Project $name=$dsp\n" if $verbose; print DSW "Project: \"$name\"=\"$dsp\" - Package Owner=<4>\r\n\r\n"; print DSW <<"EOF"; Package=<5>\r {{{\r }}}\r \r Package=<4>\r {{{\r }}}\r \r EOF } print DSW <<"EOF"; ###############################################################################\r \r Global:\r \r Package=<5>\r {{{\r }}}\r \r Package=<3>\r {{{\r }}}\r \r ###############################################################################\r \r 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 console_app_dsp_init { my $name = shift; my $dsp_name = $root_dir . $name . '.dsp'; open(DSP, ">$dsp_name") || die "Can't create $dsp_name: $!\n"; print "Creating $dsp_name\n" if $verbose; print DSP expand_here(<<"EOF"); # Microsoft Developer Studio Project File - Name="$name" - Package Owner=<4>\r # Microsoft Developer Studio Generated Build File, Format Version 6.00\r # ** DO NOT EDIT **\r \r # TARGTYPE "Win32 (x86) Console Application" 0x0103\r \r CFG=$name - Win32 Debug\r !MESSAGE This is not a valid makefile. To build this project using NMAKE,\r !MESSAGE use the Export Makefile command and run\r !MESSAGE \r !MESSAGE NMAKE /f "$name.mak".\r !MESSAGE \r !MESSAGE You can specify a configuration when running NMAKE\r !MESSAGE by defining the macro CFG on the command line. For example:\r !MESSAGE \r !MESSAGE NMAKE /f "$name.mak" CFG="$name - Win32 Debug"\r !MESSAGE \r !MESSAGE Possible choices for configuration are:\r !MESSAGE \r !MESSAGE "$name - Win32 Release" (based on "Win32 (x86) Console Application")\r !MESSAGE "$name - Win32 Debug" (based on "Win32 (x86) Console Application")\r !MESSAGE \r \r # Begin Project\r # PROP AllowPerConfigDependencies 0\r # PROP Scc_ProjName ""\r # PROP Scc_LocalPath ""\r CPP=cl.exe\r RSC=rc.exe\r \r !IF "\$(CFG)" == "$name - Win32 Release"\r \r # PROP Use_MFC 0\r # PROP Use_Debug_Libraries 0\r # PROP Output_Dir "Release"\r # PROP Intermediate_Dir "Release"\r # PROP Target_Dir ""\r # ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /c %cflags%\r # SUBTRACT CPP /YX\r # ADD RSC /l 0xc09 /d "NDEBUG"\r BSC32=bscmake.exe\r # ADD BSC32 /nologo\r LINK32=link.exe\r # 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%\r \r !ELSEIF "\$(CFG)" == "$name - Win32 Debug"\r \r # PROP Use_MFC 0\r # PROP Use_Debug_Libraries 1\r # PROP Output_Dir "Debug"\r # PROP Intermediate_Dir "Debug"\r # PROP Ignore_Export_Lib 0\r # PROP Target_Dir ""\r # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c %cflags%\r # ADD RSC /l 0xc09 /d "_DEBUG"\r BSC32=bscmake.exe\r # ADD BSC32 /nologo\r LINK32=link.exe\r # 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%\r \r !ENDIF \r \r # Begin Target\r \r # Name "$name - Win32 Release"\r # Name "$name - Win32 Debug"\r EOF close(DSP); } sub static_lib_dsp_init { my $name = shift; my $dsp_name = $root_dir . $name . '.dsp'; open(DSP, ">$dsp_name") || die "Can't create $dsp_name: $!\n"; print "Creating $dsp_name\n" if $verbose; print DSP expand_here(<<"EOF"); # Microsoft Developer Studio Project File - Name="$name" - Package Owner=<4>\r # Microsoft Developer Studio Generated Build File, Format Version 6.00\r # ** DO NOT EDIT **\r \r # TARGTYPE "Win32 (x86) Static Library" 0x0104\r \r CFG=$name - Win32 Debug\r !MESSAGE This is not a valid makefile. To build this project using NMAKE,\r !MESSAGE use the Export Makefile command and run\r !MESSAGE \r !MESSAGE NMAKE /f "$name.mak".\r !MESSAGE \r !MESSAGE You can specify a configuration when running NMAKE\r !MESSAGE by defining the macro CFG on the command line. For example:\r !MESSAGE \r !MESSAGE NMAKE /f "$name.mak" CFG="$name - Win32 Debug"\r !MESSAGE \r !MESSAGE Possible choices for configuration are:\r !MESSAGE \r !MESSAGE "$name - Win32 Release" (based on "Win32 (x86) Static Library")\r !MESSAGE "$name - Win32 Debug" (based on "Win32 (x86) Static Library")\r !MESSAGE \r \r # Begin Project\r # PROP AllowPerConfigDependencies 0\r # PROP Scc_ProjName ""\r # PROP Scc_LocalPath ""\r CPP=cl.exe\r RSC=rc.exe\r \r !IF "\$(CFG)" == "$name - Win32 Release"\r \r # PROP Use_MFC 0\r # PROP Use_Debug_Libraries 0\r # PROP Output_Dir "Release"\r # PROP Intermediate_Dir "Release"\r # PROP Target_Dir ""\r # ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /FD /c %cflags%\r # ADD RSC /l 0x409 /d "NDEBUG"\r BSC32=bscmake.exe\r # ADD BASE BSC32 /nologo\r # ADD BSC32 /nologo\r LINK32=link.exe -lib\r # ADD BASE LIB32 /nologo\r # ADD LIB32 /nologo\r \r !ELSEIF "\$(CFG)" == "$name - Win32 Debug"\r \r # PROP Use_MFC 0\r # PROP Use_Debug_Libraries 1\r # PROP Output_Dir "Debug"\r # PROP Intermediate_Dir "Debug"\r # PROP Target_Dir ""\r # ADD CPP /nologo /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /FR /FD /GZ /c %cflags%\r # ADD RSC /l 0x409 /d "_DEBUG"\r BSC32=bscmake.exe\r # ADD BASE BSC32 /nologo\r # ADD BSC32 /nologo\r LINK32=link.exe -lib\r # ADD BASE LIB32 /nologo\r # ADD LIB32 /nologo\r \r !ENDIF \r \r # Begin Target\r \r # Name "$name - Win32 Release"\r # Name "$name - Win32 Debug"\r EOF close(DSP); } sub dsp_add_source_rule { my ($fh,$dsp_name,$group,$file,$dup) = @_; print $fh "# Begin Source File\r\n"; print $fh "\r\n"; print $fh "SOURCE=$file\r\n"; if ($add_groups) { print $fh "\r\n"; print $fh "!IF \"\$(CFG)\" == \"$dsp_name - Win32 Release\"\r\n"; print $fh "\r\n"; print $fh "# PROP Intermediate_Dir \"Release\\$group\"\r\n"; print $fh "# PROP Exclude_From_Build 1\r\n" if exclude_file($file); print $fh "\r\n"; print $fh "!ELSEIF \"\$(CFG)\" == \"$dsp_name - Win32 Debug\"\r\n"; print $fh "\r\n"; print $fh "# PROP Intermediate_Dir \"Debug\\$group\"\r\n"; print $fh "# PROP Exclude_From_Build 1\r\n" if exclude_file($file); print $fh "\r\n"; print $fh "!ENDIF \r\n"; print $fh "\r\n"; } elsif ($dup) { add_dupes_dir( \*$fh, $dsp_name ); } print $fh "# End Source File\r\n"; } sub dsp_add_group { my ($dsp_name,$makefile) = @_; my $base_dir = './'; my $dsp_file = $root_dir . $dsp_name .'.dsp'; print "dsp_add_group: using dsp_name=$dsp_file, and makefile=$makefile ...\n" if $verbose2; initialize_per_input(); my $relative_dir = dirname($makefile); my $dupe = 0; read_main_am_file($root_dir . $makefile . '.am'); ###open(DSP, ">>$dsp_name" . '.dsp') open(DSP, ">>$dsp_file") || die "Can't append to $dsp_file: $!\n"; foreach my $key (sort keys %contents) { if ($key eq "include_HEADERS") { } if ($key =~ /^lib(.*)_a_SOURCES/) { my $group = 'Lib_' . $1; if ($add_groups) { print DSP "# Begin Group \"$group\"\r\n"; print DSP "\r\n"; print DSP "# PROP Default_Filter \"\"\r\n"; } my @files = split(' ', $contents{$key}); foreach (@files) { my $file; my $src_dir = $base_dir . $relative_dir . '/'; $src_dir =~ s/\//\\/g; # fixup DOS path separators if (/^\$\(([^\)]*)\)$/) { # Found a variable. my $varname = $1; foreach (split(' ', $contents{$varname})) { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); dsp_add_source_rule(\*DSP, $dsp_name, $group, $file, $dupe); } } else { $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); dsp_add_source_rule(\*DSP, $dsp_name, $group, $file, $dupe); } } if ($add_groups) { print DSP "# End Group\r\n"; } } #elsif ($key =~ /(.*)_SOURCES/) { elsif ($key eq "fgfs_SOURCES") { my $group = 'main'; if ($add_groups) { print DSP "# Begin Group \"$group\"\r\n"; print DSP "\r\n"; print DSP "# PROP Default_Filter \"\"\r\n"; } my @files = split(' ', $contents{$key}); foreach (@files) { my $file; my $src_dir = $base_dir . $relative_dir . '/'; $src_dir =~ s/\//\\/g; # fixup DOS path separators $file = $src_dir . $_; $dupe = add_2_source_list( $file, $group ); dsp_add_source_rule(\*DSP, $dsp_name, $group, $file, $dupe); } if ($add_groups) { print DSP "# End Group\r\n"; } } } close(DSP); } sub dsp_finish { my $dsp_name = shift; my $dsp_file = $root_dir . $dsp_name . '.dsp'; open(DSP, ">>$dsp_file") || die "Can't append to $dsp_file: $!\n"; foreach my $r (@extra_sources) { print DSP "# Begin Source File\r\n\r\n"; print DSP "$r\r\n"; print DSP "# End Source File\r\n"; } print DSP "# End Target\r\n"; print DSP "# End Project\r\n"; close(DSP); } # Return directory name of file. sub dirname { my ($file) = @_; my ($sub); ($sub = $file) =~ s,/+[^/]+$,,g; $sub = '.' if $sub eq $file; return $sub; } sub check_lib_paths { my $fil = shift; my $inc = ''; my $ff = ''; my $found = 0; if( ! $found ) { foreach $inc (@msvc_libs_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; if( -f $ff ) { $found = 1; last; } } } if( ! $found ) { foreach $inc (@msvc_rlibs_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; if( -f $ff ) { $found = 1; last; } } } if( ! $found ) { foreach $inc (@msvc_dlibs_paths) { $ff = $root_dir . $inc; if ( !(($ff =~ /\/$/) || ($ff =~ /\\$/)) ) { $ff .= '\\'; } $ff .= $fil; if( -f $ff ) { $found = 1; last; } } } if( $found ) { print "Found $fil in $inc [$ff] ...\n" if $verbose2; } else { print "WARNING: Unable to locate $fil ...\n" if $verbose2; } return $found; } 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 ) { $found = 1; last; } } } if( $found ) { print "Found $fil in $inc [$ff] ...\n" if $verbose2; } else { print "WARNING: Unable to locate $fil ...\n" if $verbose2; } return $found; } sub check_includes { # check for a known set of INCLUDE files my $fil = ''; my $ff = ''; my $cnt1 = 0; my $cnt2 = 0; my @missed = (); my @missed2 = (); $cnt1 = scalar @msvc_dlibs_list + scalar @msvc_rlibs_list + scalar @msvc_libs_list; print "Check each $cnt1 additional library, in each library include path ...\n" if $verbose; $cnt1 = 0; foreach $fil (@msvc_dlibs_list) { $cnt1++; if( check_lib_paths( $fil ) == 0 ) { push(@missed, $fil); } } foreach $fil (@msvc_rlibs_list) { $cnt1++; if( check_lib_paths( $fil ) == 0 ) { push(@missed, $fil); } } foreach $fil (@msvc_libs_list) { $cnt1++; if( check_lib_paths( $fil ) == 0 ) { push(@missed, $fil); } } $cnt2 = scalar @test_headers; print "Check each of $cnt2 test headers, in each include path ...\n" if $verbose; foreach $fil (@test_headers) { $cnt2++; if( check_inc_paths( $fil ) == 0 ) { push(@missed2, $fil); } } print "Done checking $cnt1 libraries, and $cnt2 test includes ...\n"; if( @missed ) { print "WARNING: Missed ". join(' ',@missed) . ".\n"; print "Check 'add_lib' and 'lib_path' in $src_cfg ...\n"; } if( @missed2 ) { print "WARNING: Missed ". join(' ',@missed2) . ".\n"; print "Check 'include_path' in $src_cfg ...\n"; } die "End check of libraries and include files ... aborting ...\n"; } # some simple utility functions sub pos_of_last_slash { my $fil = shift; my $in1 = rindex( $fil, '/' ); my $in2 = rindex( $fil, '\\' ); my $pos = -1; # if BOTH exist if (($in1 >= 0) && ($in2 >= 0)) { # get the LAST if ($in1 > $in2) { $pos = $in1; } else { $pos = $in2; } } elsif ($in1 >= 0 ) { $pos = $in1; } elsif ($in2 >= 0 ) { $pos = $in2; } return $pos; } sub file_extension { my $fil = shift; my $pos = pos_of_last_slash($fil); my $last = rindex( $fil, '.' ); my $ext = ''; if ( $last >= 0 ) { if ($pos >= 0) { if ($last > $pos) { $ext = substr($fil, $last + 1); } } else { $ext = substr($fil, $last + 1); } } return $ext; } sub file_title { my $fil = shift; my $pos = pos_of_last_slash($fil); my $last = rindex( $fil, '.' ); my $tit = ''; if ($last >= 0) { if ($pos >= 0) { if ($last > $pos) { ###print "Using 1 substr( $fil, $pos+1, $last - $pos - 1 ) ...\n"; $tit = substr( $fil, $pos+1, $last - $pos - 1 ); } else { ###print "Using 2 substr( $fil, $pos+1 ) ...\n"; $tit = substr( $fil, $pos+1 ); } } else { ###print "Using 3 substr( $fil, 0, $last ) ...\n"; $tit = substr( $fil, 0, $last ); } } elsif ($pos >= 0) { ###print "Using 4 substr( $fil, $pos+1 ) ...\n"; $tit = substr( $fil, $pos+1 ); } else { ###print "Using 5 no slash, no dot ...\n"; $tit = $fil; } return $tit; } sub add_2_source_list { my ($fil, $grp) = @_; my $fe = file_extension($fil); my $ft = lc(file_title($fil)); my $src = ($grp . '|' . $fil . '|' . $ft); my $ret = 0; if (($fe eq 'c')||($fe eq 'cxx')||($fe eq 'cpp')) { print "Add $src to C list\n" if $verbose2; 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 { print "Add $src to H list\n" if $verbose2; push(@msvc_h_files, $src); } return $ret; } sub add_dupes_dir { my ($fh, $pack) = @_; print $fh "\r\n"; print $fh "!IF \"\$(CFG)\" == \"$pack - Win32 Release\"\r\n"; print $fh "\r\n"; print $fh "# PROP Intermediate_Dir \"Release\\Dupes\"\r\n"; print $fh "\r\n"; print $fh "!ELSEIF \"\$(CFG)\" == \"$pack - Win32 Debug\"\r\n"; print $fh "\r\n"; print $fh "# PROP Intermediate_Dir \"Debug\\Dupes\"\r\n"; print $fh "\r\n"; print $fh "!ENDIF\r\n"; print $fh "\r\n"; } sub write_new_dsp { my $new_pack = 'FGFS'; my $src; my $dsp_file = $root_dir . $new_pack .'.dsp'; my @bits = (); my @done = (); my $group = ''; my $pgrp = ''; my $tit = ''; my $isdupe = 0; if ($static_lib) { static_lib_dsp_init($new_pack); } else { console_app_dsp_init($new_pack); } open(DSP, ">>$dsp_file") || die "Can't append to $dsp_file: $!\n"; if ( ! $add_groups) { print DSP "# Begin Group \"Source Files\"\r\n"; print DSP "\r\n"; print DSP "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\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\"\r\n"; print DSP "\r\n"; print DSP "# PROP Default_Filter \"\"\r\n"; } else { # not adding groups, check duplicate names foreach my $tt (@done) { if( $tt eq $tit ) { $isdupe = 1; last; } } } ###dsp_add_group($dsp_package, $am_file) if !exclude_dir($am_file); 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\r\n"; } $pgrp = $group; } if ( !$add_groups) { print DSP "# End Group\r\n"; } # just the HEADER files print DSP "# Begin Group \"Header Files\"\r\n"; print DSP "\r\n"; print DSP "# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\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\r\n"; close(DSP); $add_groups = $savgrp; dsp_finish($new_pack); generate_dsw($new_pack); } sub prt { my $msg = shift; print $msg; print $LOG $msg; } sub amend_vcproj { my $src_lib = $root_dir . 'projects\VC8\FlightGearLib.vcproj'; my $src_main = $root_dir . 'projects\VC8\FlightGear.vcproj'; my $line = ''; if ( ! -f $src_lib ) { print "AWK: Unable to locate [$src_lib] file ...\n"; return 1; } if ( ! -f $src_main ) { print "AWK: Unable to locate [$src_main] file ...\n"; return 2; } open IF, "<$src_lib" or die "Can not OPEN $src_lib!\n"; my @lib_lines = <IF>; # slurp whole file, to an array of lines close(IF); open IF, "<$src_main" or die "Can not OPEN $src_main!\n"; my @main_lines = <IF>; # slurp whole file, to an array of lines close(IF); my $lc_lib = scalar @lib_lines; my $lc_main = scalar @main_lines; print "Loaded $src_lib of $lc_lib lines ...\n"; print "Loaded $src_main of $lc_main lines ...\n"; foreach $line (@main_lines) { } return 0; } # eof - am2dsp4.pl