am2dsp4.pl to HTML.

index -|- end

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} .= &quote_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, &quote_cond_val ($val));
             }
             else
             {
            push (@new_vals, shift (@cond_vals));
             }
         }
         if ($found)
         {
             $conditional{$last_var_name}
                 = join (' ', @new_vals);
         }
          }
          if (! $found)
          {
         &check_ambiguous_conditional ($last_var_name,
                        $cond_string);
         $conditional{$last_var_name} .= ' ';
         $val = $value;
          }
      }
      else
      {
          $conditional{$last_var_name} = '';
          $val = $contents{$last_var_name};
      }
      if (! $found)
      {
          $conditional{$last_var_name} .= ($cond_string
                       . ' '
                       . &quote_cond_val ($val));
      }
       }
       # FIXME: this doesn't always work correctly; it will group
       # all comments for a given variable, no matter where
       # defined.
       $am_vars{$last_var_name} = $comment . $spacing;
       $def_type{$last_var_name} = ($type eq ':') ? ':' : '';
       push (@var_list, $last_var_name);
       $comment = $spacing = '';
       $saw_bk = /\\$/;
       # Error if bogus.
       &am_line_error ($., "bad macro name \`$last_var_name'")
      if ! $is_ok_macro;
   }
        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

index -|- top

checked by tidy  Valid HTML 4.01 Transitional