NASM: relicense under the 2-clause BSD license
[platform/upstream/nasm.git] / mkdep.pl
index 69743f6..9f80ed3 100755 (executable)
--- a/mkdep.pl
+++ b/mkdep.pl
@@ -1,17 +1,63 @@
 #!/usr/bin/perl
+## --------------------------------------------------------------------------
+##   
+##   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+##   See the file AUTHORS included with the NASM distribution for
+##   the specific copyright holders.
+##
+##   Copyright 1996-2009 the NASM Authors - All rights reserved.
+##
+##   Redistribution and use in source and binary forms, with or without
+##   modification, are permitted provided that the following
+##   conditions are met:
+##
+##   * Redistributions of source code must retain the above copyright
+##     notice, this list of conditions and the following disclaimer.
+##   * Redistributions in binary form must reproduce the above
+##     copyright notice, this list of conditions and the following
+##     disclaimer in the documentation and/or other materials provided
+##     with the distribution.
+##     
+##     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+##     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+##     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+##     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+##     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+##     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+##     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+##     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+##     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+##     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+##     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+##     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+##     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+## --------------------------------------------------------------------------
+
 #
 # Script to create Makefile-style dependencies.
 #
-# Usage: perl [-s path-separator] [-o obj-ext] mkdep.pl dir... > deps
+# Usage: perl mkdep.pl [-s path-separator] [-o obj-ext] dir... > deps
 #
 
+use File::Spec;
+use File::Basename;
+use Fcntl;
+
+$barrier = "#-- Everything below is generated by mkdep.pl - do not edit --#\n";
+
+#
+# Scan files for dependencies
+#
 sub scandeps($) {
     my($file) = @_;
     my($line, $nf);
     my(@xdeps) = ();
     my(@mdeps) = ();
 
-    open(FILE, "< $file\0") or return; # If not openable, assume generated
+    sysopen(FILE, $file, O_RDONLY)
+       or return;              # If not openable, assume generated
+
     while ( defined($line = <FILE>) ) {
        chomp $line;
        $line =~ s:/\*.*\*/::g;
@@ -43,23 +89,134 @@ sub alldeps($) {
            $adeps{$idep} = 1;
        }
     }
-    return keys(%adeps);
+    return sort(keys(%adeps));
+}
+
+# This converts a filename from host syntax to target syntax
+# This almost certainly works only on relative filenames...
+sub convert_file($$) {
+    my($file,$sep) = @_;
+    my(@fspec) = (basename($file));
+    while ( ($file = dirname($file)) ne File::Spec->curdir() &&
+           $file ne File::Spec->rootdir() ) {
+       unshift(@fspec, basename($file));
+    }
+
+    if ( $sep eq '' ) {
+       # This means kill path completely.  Used with Makes who do
+       # path searches, but doesn't handle output files in subdirectories,
+       # like OpenWatcom WMAKE.
+       return $fspec[scalar(@fspec)-1];
+    } else {
+       return join($sep, @fspec);
+    }
+}
+
+#
+# Insert dependencies into a Makefile
+#
+sub insert_deps($) {
+    my($file) = @_;
+    $nexttemp++;               # Unique serial number for each temp file
+    my($tmp) = File::Spec->catfile(dirname($file), 'tmp.'.$nexttemp);
+
+    sysopen(IN, $file, O_RDONLY)
+       or die "$0: Cannot open input: $file\n";
+    sysopen(OUT, $tmp, O_WRONLY|O_CREAT|O_TRUNC, 0666)
+       or die "$0: Cannot open output: $tmp\n";
+
+    my($line,$parm,$val);
+    my($obj) = '.o';           # Defaults
+    my($sep) = '/';
+    my($cont) = "\\";
+    my($maxline) = 78;         # Seems like a reasonable default
+    my @exclude = ();          # Don't exclude anything
+
+    while ( defined($line = <IN>) ) {
+       if ( $line =~ /^\s*\#\s*@([a-z0-9-]+):\s*\"([^\"]*)\"/ ) {
+           $parm = $1;  $val = $2;
+           if ( $parm eq 'object-ending' ) {
+               $obj = $val;
+           } elsif ( $parm eq 'path-separator' ) {
+               $sep = $val;
+           } elsif ( $parm eq 'line-width' ) {
+               $maxline = $val+0;
+           } elsif ( $parm eq 'continuation' ) {
+               $cont = $val;
+           } elsif ( $parm eq 'exclude' ) {
+               @exclude = split(/\,/, $val);
+           }
+       } elsif ( $line eq $barrier ) {
+           last;               # Stop reading input at barrier line
+       }
+       print OUT $line;
+    }
+    close(IN);
+
+    my $e;
+    my %do_exclude = ();
+    foreach $e (@exclude) {
+       $do_exclude{$e} = 1;
+    }
+
+    my $dfile, $ofile, $str, $sl, $len;
+    my @deps, $dep;
+
+    print OUT $barrier;
+
+    foreach $dfile ( sort(keys(%deps)) ) {
+       if ( $dfile =~ /\.[Cc]$/ ) {
+           $ofile = $dfile; $ofile =~ s/\.[Cc]$//;
+           $str = convert_file($ofile,$sep).$obj.':';
+           $len = length($str);
+           print OUT $str;
+           foreach $dep ($dfile, alldeps($dfile)) {
+               unless ($do_exclude{$dep}) {
+                   $str = convert_file($dep,$sep);
+                   $sl = length($str)+1;
+                   if ( $len+$sl > $maxline-2 ) {
+                       print OUT ' ', $cont, "\n ", $str;
+                       $len = $sl;
+                   } else {
+                       print OUT ' ', $str;
+                       $len += $sl;
+                   }
+               }
+           }
+           print OUT "\n";
+       }
+    }
+    close(OUT);
+
+    (unlink($file) && rename($tmp, $file))
+       or die "$0: Failed to change $tmp -> $file\n";
 }
 
+#
+# Main program
+#
+
 %deps = ();
 @files = ();
-$sep = '/';                    # Default, and works on most systems
-$obj = 'o';                    # Object file extension
+@mkfiles = ();
+$mkmode = 0;
 
 while ( defined($arg = shift(@ARGV)) ) {
-    if ( $arg =~ /^\-s$/ ) {
-       $sep = shift(@ARGV);
-    } elsif ( $arg =~ /^\-o$/ ) {
-       $obj = shift(@ARGV);
+    if ( $arg eq '-m' ) {
+       $arg = shift(@ARGV);
+       push(@mkfiles, $arg);
+    } elsif ( $arg eq '-M' ) {
+       $mkmode = 1;            # Futher filenames are output Makefile names
+    } elsif ( $arg eq '--' && $mkmode ) {
+       $mkmode = 0;
     } elsif ( $arg =~ /^-/ ) {
        die "Unknown option: $arg\n";
     } else {
-       push(@files, $arg);
+       if ( $mkmode ) {
+           push(@mkfiles, $arg);
+       } else {
+           push(@files, $arg);
+       }
     }
 }
 
@@ -67,7 +224,8 @@ foreach $dir ( @files ) {
     opendir(DIR, $dir) or die "$0: Cannot open directory: $dir";
 
     while ( $file = readdir(DIR) ) {
-       $path = ($dir eq '.') ? $file : $dir.$sep.$file;
+       $path = ($dir eq File::Spec->curdir())
+           ? $file : File::Spec->catfile($dir,$file);
        if ( $file =~ /\.[Cc]$/ ) {
            scandeps($path);
        }
@@ -75,12 +233,6 @@ foreach $dir ( @files ) {
     closedir(DIR);
 }
 
-foreach $file ( sort(keys(%deps)) ) {
-    if ( $file =~ /\.[Cc]$/ ) {
-       $ofile = $file; $ofile =~ s/\.[Cc]$/\./; $ofile .= $obj;
-       print $ofile, ': ', $file, ' ';
-       print join(' ', alldeps($file));
-       print "\n";
-    }
+foreach $mkfile ( @mkfiles ) {
+    insert_deps($mkfile);
 }
-