summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2016-05-25 12:06:29 -0700
committerH. Peter Anvin <hpa@zytor.com>2016-05-25 12:06:29 -0700
commite1f985c167495185c55c46e640f2607604597383 (patch)
tree3ddd11d12e6a3bf6e21c39d1342175d5488d8d39 /tools
parent22538e2b6713d6e4e05fb82c6969320a519b4c93 (diff)
downloadnasm-e1f985c167495185c55c46e640f2607604597383.tar.gz
Reorganize the source code into subdirectories
Make the source code easier to understand and keep track of by organizing it into subdirectories depending on the function. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/cleanfile176
-rwxr-xr-xtools/cleanpatch258
-rwxr-xr-xtools/mkdep.pl259
-rwxr-xr-xtools/release101
-rwxr-xr-xtools/syncfiles.pl126
-rwxr-xr-xtools/tag-release58
6 files changed, 978 insertions, 0 deletions
diff --git a/tools/cleanfile b/tools/cleanfile
new file mode 100755
index 00000000..cefd29e5
--- /dev/null
+++ b/tools/cleanfile
@@ -0,0 +1,176 @@
+#!/usr/bin/perl -w
+#
+# Clean a text file -- or directory of text files -- of stealth whitespace.
+# WARNING: this can be a highly destructive operation. Use with caution.
+#
+
+use bytes;
+use File::Basename;
+
+# Default options
+$max_width = 79;
+
+# Clean up space-tab sequences, either by removing spaces or
+# replacing them with tabs.
+sub clean_space_tabs($)
+{
+ no bytes; # Tab alignment depends on characters
+
+ my($li) = @_;
+ my($lo) = '';
+ my $pos = 0;
+ my $nsp = 0;
+ my($i, $c);
+
+ for ($i = 0; $i < length($li); $i++) {
+ $c = substr($li, $i, 1);
+ if ($c eq "\t") {
+ my $npos = ($pos+$nsp+8) & ~7;
+ my $ntab = ($npos >> 3) - ($pos >> 3);
+ $lo .= "\t" x $ntab;
+ $pos = $npos;
+ $nsp = 0;
+ } elsif ($c eq "\n" || $c eq "\r") {
+ $lo .= " " x $nsp;
+ $pos += $nsp;
+ $nsp = 0;
+ $lo .= $c;
+ $pos = 0;
+ } elsif ($c eq " ") {
+ $nsp++;
+ } else {
+ $lo .= " " x $nsp;
+ $pos += $nsp;
+ $nsp = 0;
+ $lo .= $c;
+ $pos++;
+ }
+ }
+ $lo .= " " x $nsp;
+ return $lo;
+}
+
+# Compute the visual width of a string
+sub strwidth($) {
+ no bytes; # Tab alignment depends on characters
+
+ my($li) = @_;
+ my($c, $i);
+ my $pos = 0;
+ my $mlen = 0;
+
+ for ($i = 0; $i < length($li); $i++) {
+ $c = substr($li,$i,1);
+ if ($c eq "\t") {
+ $pos = ($pos+8) & ~7;
+ } elsif ($c eq "\n") {
+ $mlen = $pos if ($pos > $mlen);
+ $pos = 0;
+ } else {
+ $pos++;
+ }
+ }
+
+ $mlen = $pos if ($pos > $mlen);
+ return $mlen;
+}
+
+$name = basename($0);
+
+@files = ();
+
+while (defined($a = shift(@ARGV))) {
+ if ($a =~ /^-/) {
+ if ($a eq '-width' || $a eq '-w') {
+ $max_width = shift(@ARGV)+0;
+ } else {
+ print STDERR "Usage: $name [-width #] files...\n";
+ exit 1;
+ }
+ } else {
+ push(@files, $a);
+ }
+}
+
+foreach $f ( @files ) {
+ print STDERR "$name: $f\n";
+
+ if (! -f $f) {
+ print STDERR "$f: not a file\n";
+ next;
+ }
+
+ if (!open(FILE, '+<', $f)) {
+ print STDERR "$name: Cannot open file: $f: $!\n";
+ next;
+ }
+
+ binmode FILE;
+
+ # First, verify that it is not a binary file; consider any file
+ # with a zero byte to be a binary file. Is there any better, or
+ # additional, heuristic that should be applied?
+ $is_binary = 0;
+
+ while (read(FILE, $data, 65536) > 0) {
+ if ($data =~ /\0/) {
+ $is_binary = 1;
+ last;
+ }
+ }
+
+ if ($is_binary) {
+ print STDERR "$name: $f: binary file\n";
+ next;
+ }
+
+ seek(FILE, 0, 0);
+
+ $in_bytes = 0;
+ $out_bytes = 0;
+ $blank_bytes = 0;
+
+ @blanks = ();
+ @lines = ();
+ $lineno = 0;
+
+ while ( defined($line = <FILE>) ) {
+ $lineno++;
+ $in_bytes += length($line);
+ $line =~ s/[ \t\r]*$//; # Remove trailing spaces
+ $line = clean_space_tabs($line);
+
+ if ( $line eq "\n" ) {
+ push(@blanks, $line);
+ $blank_bytes += length($line);
+ } else {
+ push(@lines, @blanks);
+ $out_bytes += $blank_bytes;
+ push(@lines, $line);
+ $out_bytes += length($line);
+ @blanks = ();
+ $blank_bytes = 0;
+ }
+
+ $l_width = strwidth($line);
+ if ($max_width && $l_width > $max_width) {
+ print STDERR
+ "$f:$lineno: line exceeds $max_width characters ($l_width)\n";
+ }
+ }
+
+ # Any blanks at the end of the file are discarded
+
+ if ($in_bytes != $out_bytes) {
+ # Only write to the file if changed
+ seek(FILE, 0, 0);
+ print FILE @lines;
+
+ if ( !defined($where = tell(FILE)) ||
+ !truncate(FILE, $where) ) {
+ die "$name: Failed to truncate modified file: $f: $!\n";
+ }
+ }
+
+ close(FILE);
+}
diff --git a/tools/cleanpatch b/tools/cleanpatch
new file mode 100755
index 00000000..9680d03a
--- /dev/null
+++ b/tools/cleanpatch
@@ -0,0 +1,258 @@
+#!/usr/bin/perl -w
+#
+# Clean a patch file -- or directory of patch files -- of stealth whitespace.
+# WARNING: this can be a highly destructive operation. Use with caution.
+#
+
+use bytes;
+use File::Basename;
+
+# Default options
+$max_width = 79;
+
+# Clean up space-tab sequences, either by removing spaces or
+# replacing them with tabs.
+sub clean_space_tabs($)
+{
+ no bytes; # Tab alignment depends on characters
+
+ my($li) = @_;
+ my($lo) = '';
+ my $pos = 0;
+ my $nsp = 0;
+ my($i, $c);
+
+ for ($i = 0; $i < length($li); $i++) {
+ $c = substr($li, $i, 1);
+ if ($c eq "\t") {
+ my $npos = ($pos+$nsp+8) & ~7;
+ my $ntab = ($npos >> 3) - ($pos >> 3);
+ $lo .= "\t" x $ntab;
+ $pos = $npos;
+ $nsp = 0;
+ } elsif ($c eq "\n" || $c eq "\r") {
+ $lo .= " " x $nsp;
+ $pos += $nsp;
+ $nsp = 0;
+ $lo .= $c;
+ $pos = 0;
+ } elsif ($c eq " ") {
+ $nsp++;
+ } else {
+ $lo .= " " x $nsp;
+ $pos += $nsp;
+ $nsp = 0;
+ $lo .= $c;
+ $pos++;
+ }
+ }
+ $lo .= " " x $nsp;
+ return $lo;
+}
+
+# Compute the visual width of a string
+sub strwidth($) {
+ no bytes; # Tab alignment depends on characters
+
+ my($li) = @_;
+ my($c, $i);
+ my $pos = 0;
+ my $mlen = 0;
+
+ for ($i = 0; $i < length($li); $i++) {
+ $c = substr($li,$i,1);
+ if ($c eq "\t") {
+ $pos = ($pos+8) & ~7;
+ } elsif ($c eq "\n") {
+ $mlen = $pos if ($pos > $mlen);
+ $pos = 0;
+ } else {
+ $pos++;
+ }
+ }
+
+ $mlen = $pos if ($pos > $mlen);
+ return $mlen;
+}
+
+$name = basename($0);
+
+@files = ();
+
+while (defined($a = shift(@ARGV))) {
+ if ($a =~ /^-/) {
+ if ($a eq '-width' || $a eq '-w') {
+ $max_width = shift(@ARGV)+0;
+ } else {
+ print STDERR "Usage: $name [-width #] files...\n";
+ exit 1;
+ }
+ } else {
+ push(@files, $a);
+ }
+}
+
+foreach $f ( @files ) {
+ print STDERR "$name: $f\n";
+
+ if (! -f $f) {
+ print STDERR "$f: not a file\n";
+ next;
+ }
+
+ if (!open(FILE, '+<', $f)) {
+ print STDERR "$name: Cannot open file: $f: $!\n";
+ next;
+ }
+
+ binmode FILE;
+
+ # First, verify that it is not a binary file; consider any file
+ # with a zero byte to be a binary file. Is there any better, or
+ # additional, heuristic that should be applied?
+ $is_binary = 0;
+
+ while (read(FILE, $data, 65536) > 0) {
+ if ($data =~ /\0/) {
+ $is_binary = 1;
+ last;
+ }
+ }
+
+ if ($is_binary) {
+ print STDERR "$name: $f: binary file\n";
+ next;
+ }
+
+ seek(FILE, 0, 0);
+
+ $in_bytes = 0;
+ $out_bytes = 0;
+ $lineno = 0;
+
+ @lines = ();
+
+ $in_hunk = 0;
+ $err = 0;
+
+ while ( defined($line = <FILE>) ) {
+ $lineno++;
+ $in_bytes += length($line);
+
+ if (!$in_hunk) {
+ if ($line =~
+ /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@/) {
+ $minus_lines = $2;
+ $plus_lines = $4;
+ if ($minus_lines || $plus_lines) {
+ $in_hunk = 1;
+ @hunk_lines = ($line);
+ }
+ } else {
+ push(@lines, $line);
+ $out_bytes += length($line);
+ }
+ } else {
+ # We're in a hunk
+
+ if ($line =~ /^\+/) {
+ $plus_lines--;
+
+ $text = substr($line, 1);
+ $text =~ s/[ \t\r]*$//; # Remove trailing spaces
+ $text = clean_space_tabs($text);
+
+ $l_width = strwidth($text);
+ if ($max_width && $l_width > $max_width) {
+ print STDERR
+ "$f:$lineno: adds line exceeds $max_width ",
+ "characters ($l_width)\n";
+ }
+
+ push(@hunk_lines, '+'.$text);
+ } elsif ($line =~ /^\-/) {
+ $minus_lines--;
+ push(@hunk_lines, $line);
+ } elsif ($line =~ /^ /) {
+ $plus_lines--;
+ $minus_lines--;
+ push(@hunk_lines, $line);
+ } else {
+ print STDERR "$name: $f: malformed patch\n";
+ $err = 1;
+ last;
+ }
+
+ if ($plus_lines < 0 || $minus_lines < 0) {
+ print STDERR "$name: $f: malformed patch\n";
+ $err = 1;
+ last;
+ } elsif ($plus_lines == 0 && $minus_lines == 0) {
+ # End of a hunk. Process this hunk.
+ my $i;
+ my $l;
+ my @h = ();
+ my $adj = 0;
+ my $done = 0;
+
+ for ($i = scalar(@hunk_lines)-1; $i > 0; $i--) {
+ $l = $hunk_lines[$i];
+ if (!$done && $l eq "+\n") {
+ $adj++; # Skip this line
+ } elsif ($l =~ /^[ +]/) {
+ $done = 1;
+ unshift(@h, $l);
+ } else {
+ unshift(@h, $l);
+ }
+ }
+
+ $l = $hunk_lines[0]; # Hunk header
+ undef @hunk_lines; # Free memory
+
+ if ($adj) {
+ die unless
+ ($l =~ /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@(.*)$/);
+ my $mstart = $1;
+ my $mlin = $2;
+ my $pstart = $3;
+ my $plin = $4;
+ my $tail = $5; # doesn't include the final newline
+
+ $l = sprintf("@@ -%d,%d +%d,%d @@%s\n",
+ $mstart, $mlin, $pstart, $plin-$adj,
+ $tail);
+ }
+ unshift(@h, $l);
+
+ # Transfer to the output array
+ foreach $l (@h) {
+ $out_bytes += length($l);
+ push(@lines, $l);
+ }
+
+ $in_hunk = 0;
+ }
+ }
+ }
+
+ if ($in_hunk) {
+ print STDERR "$name: $f: malformed patch\n";
+ $err = 1;
+ }
+
+ if (!$err) {
+ if ($in_bytes != $out_bytes) {
+ # Only write to the file if changed
+ seek(FILE, 0, 0);
+ print FILE @lines;
+
+ if ( !defined($where = tell(FILE)) ||
+ !truncate(FILE, $where) ) {
+ die "$name: Failed to truncate modified file: $f: $!\n";
+ }
+ }
+ }
+
+ close(FILE);
+}
diff --git a/tools/mkdep.pl b/tools/mkdep.pl
new file mode 100755
index 00000000..50d509c3
--- /dev/null
+++ b/tools/mkdep.pl
@@ -0,0 +1,259 @@
+#!/usr/bin/perl
+## --------------------------------------------------------------------------
+##
+## Copyright 1996-2016 The NASM Authors - All Rights Reserved
+## See the file AUTHORS included with the NASM distribution for
+## the specific copyright holders.
+##
+## 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 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";
+
+# This converts from filenames to full pathnames for our dependencies
+%dep_path = {};
+
+#
+# Scan files for dependencies
+#
+sub scandeps($) {
+ my($file) = @_;
+ my($line, $nf);
+ my(@xdeps) = ();
+ my(@mdeps) = ();
+
+ open(my $fh, '<', $file)
+ or return; # If not openable, assume generated
+
+ while ( defined($line = <$fh>) ) {
+ chomp $line;
+ $line =~ s:/\*.*\*/::g;
+ $line =~ s://.*$::;
+ if ( $line =~ /^\s*\#\s*include\s+\"(.*)\"\s*$/ ) {
+ $nf = $1;
+ push(@mdeps, $nf);
+ push(@xdeps, $nf) unless ( defined($deps{$nf}) );
+ }
+ }
+ close($fh);
+ $deps{$file} = [@mdeps];
+
+ foreach $file ( @xdeps ) {
+ scandeps($file);
+ }
+}
+
+# %deps contains direct dependencies. This subroutine resolves
+# indirect dependencies that result.
+sub alldeps($) {
+ my($file) = @_;
+ my(%adeps);
+ my($dep,$idep);
+
+ foreach $dep ( @{$deps{$file}} ) {
+ $adeps{$dep} = 1;
+ foreach $idep ( alldeps($dep) ) {
+ $adeps{$idep} = 1;
+ }
+ }
+ 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);
+
+ open(my $in, '<', $file)
+ or die "$0: Cannot open input: $file\n";
+ open(my $out, '>', $tmp)
+ 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
+ my @genhdrs = ();
+
+ while ( defined($line = <$in>) ) {
+ if ( $line =~ /^([^\s\#\$\:]+\.h):/ ) {
+ # Note: we trust the first Makefile given best
+ my $fpath = $1;
+ my $fbase = basename($fpath);
+ if (!defined($dep_path{$fbase})) {
+ $dep_path{$fbase} = $fpath;
+ print STDERR "Makefile: $fbase -> $fpath\n";
+ }
+ } elsif ( $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 = $1;
+ $str = convert_file($ofile, $sep).$obj.':';
+ $len = length($str);
+ print $out $str;
+ foreach $dep ($dfile, alldeps($dfile)) {
+ unless ($do_exclude{$dep}) {
+ if (!defined($dep_path{$dep})) {
+ if ($dep eq $dfile) {
+ $dep_path{$dep} = $dfile;
+ print STDERR "Self: $dep -> $dfile\n";
+ } else {
+ die "$0: unknown dependency: $dep\n";
+ }
+ }
+ $str = convert_file($dep_path{$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
+#
+
+my %deps = ();
+my @files = ();
+my @mkfiles = ();
+my $mkmode = 0;
+
+while ( defined(my $arg = 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 {
+ if ( $mkmode ) {
+ push(@mkfiles, $arg);
+ } else {
+ push(@files, $arg);
+ }
+ }
+}
+
+foreach my $dir ( @files ) {
+ opendir(DIR, $dir) or die "$0: Cannot open directory: $dir";
+
+ while ( my $file = readdir(DIR) ) {
+ $path = ($dir eq File::Spec->curdir())
+ ? $file : File::Spec->catfile($dir,$file);
+ if ( $file =~ /\.[Cc]$/ ) {
+ scandeps($path);
+ } elsif ( $file =~ /\.[Hh]$/ ) {
+ print STDERR "Filesystem: $file -> $path\n";
+ $dep_path{$file} = $path;
+ }
+ }
+ closedir(DIR);
+}
+
+foreach $mkfile ( @mkfiles ) {
+ insert_deps($mkfile);
+}
diff --git a/tools/release b/tools/release
new file mode 100755
index 00000000..14e750a6
--- /dev/null
+++ b/tools/release
@@ -0,0 +1,101 @@
+#!/bin/bash -xe
+#
+# Generate a NASM release
+#
+# Usage: release version [destination]
+#
+
+version="$1"
+if [ -z "$1" ]; then
+ echo "Usage: $0 version [destination]" 1>&2
+ exit 1
+fi
+
+WHERE="$2"
+if [ -z "$WHERE" ]; then
+ WHERE=/var/tmp
+fi
+
+if [ -n "$GIT_DIR" ]; then
+ HERE="$GIT_DIR"
+else
+ HERE=`pwd`
+fi
+
+if [ x`cat version` != x"${version}" ]; then
+ echo "${version}" > version
+ git update-index version
+ git commit -m "Version ${version}" -- version
+fi
+git tag -m "NASM version ${version}" -f "nasm-${version}"
+
+cd "$WHERE"
+rm -rf nasm-release.*
+work=nasm-release.$$
+mkdir $work
+cd $work
+unset GIT_DIR
+git clone -s -l "$HERE" nasm
+rm -rf nasm/.git nasm/.gitignore
+
+# Create files which are in the release but automatically generated
+cd nasm
+./autogen.sh
+./configure --prefix=/usr/local
+make perlreq spec manpages
+make alldeps
+make distclean
+cd ..
+
+# Clean up any previous attempt
+rm -f ../nasm-"$version".tar.gz ../nasm-"$version"-xdoc.tar.gz
+rm -f ../nasm-"$version".tar.bz2 ../nasm-"$version"-xdoc.tar.bz2
+rm -f ../nasm-"$version".tar.xz ../nasm-"$version"-xdoc.tar.xz
+rm -f ../nasm-"$version".zip ../nasm-"$version"-xdoc.zip
+
+# Create tarfile (Unix convention: file includes prefix)
+mv nasm nasm-"$version"
+tar cvvf nasm-"$version".tar nasm-"$version"
+xz -9ek nasm-"$version".tar
+bzip2 -9k nasm-"$version".tar
+gzip -9 nasm-"$version".tar
+mv nasm-"$version".tar.gz nasm-"$version".tar.bz2 nasm-"$version".tar.xz ..
+
+# Create zipfile (DOS convention: no prefix, convert file endings)
+cd nasm-"$version"
+zip -9Dlr ../../nasm-"$version".zip * -x \*.jpg -x \*.zip -x \*.ico # Text files
+zip -9Dgr ../../nasm-"$version".zip * -i \*.jpg -i \*.zip -i \*.ico # Binary files
+cd ..
+
+# Record what we have already generated
+find nasm-"$version" -not -type d -print > main
+
+# Create documentation
+cd nasm-"$version"
+./configure --prefix=/usr/local
+make doc
+# Remove intermediate files.
+make cleaner
+cd ..
+
+# Remove non-documentation
+cat main | xargs rm -f
+# Delete empty subdirectories
+find nasm-"$version"/doc -type d -exec rmdir '{}' \; 2>/dev/null || true
+
+# Create doc tarfile
+tar cvvf nasm-"$version"-xdoc.tar nasm-"$version"/doc
+xz -9ek nasm-"$version"-xdoc.tar
+bzip2 -9k nasm-"$version"-xdoc.tar
+gzip -9 nasm-"$version"-xdoc.tar
+mv nasm-"$version"-xdoc.tar.gz nasm-"$version"-xdoc.tar.bz2 nasm-"$version"-xdoc.tar.xz ..
+
+# Create doc zipfile (DOS convention: no prefix, convert file endings)
+# (Note: generating Win .hlp files requires additional tools)
+cd nasm-"$version"
+zip -9Dlr ../../nasm-"$version"-xdoc.zip doc -x \*.pdf -x \*.info\*
+zip -9Dgr ../../nasm-"$version"-xdoc.zip doc -i \*.pdf -i \*.info\*
+
+# Clean up
+cd ../..
+rm -rf "$work"
diff --git a/tools/syncfiles.pl b/tools/syncfiles.pl
new file mode 100755
index 00000000..4da87f9c
--- /dev/null
+++ b/tools/syncfiles.pl
@@ -0,0 +1,126 @@
+#!/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.
+##
+## 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.
+##
+## --------------------------------------------------------------------------
+
+#
+# Sync the output file list between Makefiles
+# Use the mkdep.pl parameters to get the filename syntax
+#
+# The first file is the source file; the other ones target.
+#
+%def_hints = ('object-ending' => '.o',
+ 'path-separator' => '/',
+ 'continuation' => "\\");
+
+sub do_transform($$) {
+ my($l, $h) = @_;
+ my($ps) = $$h{'path-separator'};
+
+ $l =~ s/\x01/$$h{'object-ending'}/g;
+ $l =~ s/\x03/$$h{'continuation'}/g;
+
+ if ($ps eq '') {
+ # Remove the path separator and the preceeding directory
+ $l =~ s/[^\s\=]*\x02//g;
+ } else {
+ # Convert the path separator
+ $l =~ s/\x02/$ps/g;
+ }
+
+ return $l;
+}
+
+@file_list = ();
+
+$first = 1;
+$first_file = $ARGV[0];
+die unless (defined($first_file));
+
+foreach $file (@ARGV) {
+ open(FILE, "< $file\0") or die;
+
+ # First, read the syntax hints
+ %hints = %def_hints;
+ while (defined($line = <FILE>)) {
+ if ( $line =~ /^\s*\#\s*@([a-z0-9-]+):\s*\"([^\"]*)\"/ ) {
+ $hints{$1} = $2;
+ }
+ }
+
+ # Read and process the file
+ seek(FILE,0,0);
+ @lines = ();
+ $processing = 0;
+ while (defined($line = <FILE>)) {
+ chomp $line;
+ if ($processing) {
+ if ($line eq '#-- End File Lists --#') {
+ push(@lines, $line."\n");
+ $processing = 0;
+ } elsif ($first) {
+ my $xl = $line;
+ my $oe = "\Q$hints{'object-ending'}";
+ my $ps = "\Q$hints{'path-separator'}";
+ my $cn = "\Q$hints{'continuation'}";
+
+ $xl =~ s/${oe}(\s|$)/\x01$1/g;
+ $xl =~ s/${ps}/\x02/g;
+ $xl =~ s/${cn}$/\x03/;
+ push(@file_list, $xl);
+ push(@lines, $line);
+ }
+ } else {
+ push(@lines, $line."\n");
+ if ($line eq '#-- Begin File Lists --#') {
+ $processing = 1;
+ if (!$first) {
+ push(@lines, "# Edit in $first_file, not here!\n");
+ foreach $l (@file_list) {
+ push(@lines, do_transform($l, \%hints)."\n");
+ }
+ }
+ }
+ }
+ }
+ close(FILE);
+
+ # Write the file back out
+ if (!$first) {
+ open(FILE, "> $file\0") or die;
+ print FILE @lines;
+ close(FILE);
+ }
+
+ undef @lines;
+ $first = 0;
+}
diff --git a/tools/tag-release b/tools/tag-release
new file mode 100755
index 00000000..9e3a0bd0
--- /dev/null
+++ b/tools/tag-release
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+version=""
+repo=""
+branch=""
+push=0
+
+for opt; do
+ case "$opt" in
+ --ver=*)
+ version=`echo $opt | sed 's/[-a-zA-Z0-9]*=//'`
+ ;;
+ --repo=*)
+ repo=`echo $opt | sed 's/[-a-zA-Z0-9]*=//'`
+ ;;
+ --branch=*)
+ branch=`echo $opt | sed 's/[-a-zA-Z0-9]*=//'`
+ ;;
+ --push)
+ push=1
+ ;;
+ --no-push)
+ push=0
+ ;;
+ -*)
+ echo "Invalid option: $opt" 1>&2
+ exit 1
+ ;;
+ *)
+ version=$opt
+ ;;
+ esac
+done
+
+if [ -z "$version" ]; then
+ echo " Usage"
+ echo " $0 --ver=num [--repo=name --branch=name --push]" 1>&2
+ echo " Example"
+ echo " $0 --ver=2.10rc1 --repo=git+ssh://user@repo.or.cz/nasm.git --branch=master --no-push" 1>&2
+ echo " With --no-push the changes are not pushed out to remote repo"
+ exit 1
+fi
+
+tag="nasm-$version"
+
+echo "$version" > version
+git add version
+git commit -m "NASM $version"
+git tag -a -m "NASM $version" "$tag"
+
+if [ $push = 1 ]; then
+ set -x
+ git push $repo $branch
+ git push $repo $tag
+ git push --tags $repo
+ set +x
+fi
+