This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFT/RFA] bashjar patch
- From: Paolo Bonzini <bonzini at gnu dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 28 Apr 2006 23:31:01 +0200
- Subject: [RFT/RFA] bashjar patch
Hello,
this is the patch to implement a jar tool as a shell script, fixed to
implement -C as in Sun's jar tool. Bootstrapped/regtested
i686-pc-linux-gnu, ok to apply when I come back on May 15th?
Testing is appreciated with shells other than bash.
Paolo
2006-04-04 Paolo Bonzini <bonzini@gnu.org>
* configure.ac (ZIP, UNZIP): New programs.
(JAR): Fall back to bash script. Generate it.
(BASH_JAR): New conditional.
* jar.in: New file.
* Makefile.am (bin_SCRIPTS): Add JAR.
(JAR): New, overriding default definition from Automake.
Index: Makefile.am
===================================================================
--- Makefile.am (revision 113241)
+++ Makefile.am (working copy)
@@ -89,7 +89,11 @@ bin_SCRIPTS = addr2name.awk
## Compilers and compilation flags.
##
-GCJH = @GCJH@
+if BASH_JAR
+bin_SCRIPTS += scripts/jar
+endif
+
+JAR := $(patsubst ./%, $(shell pwd)/%, @JAR@)
## The compiler with whatever flags we want for both -c and -C
## compiles.
Index: configure.ac
===================================================================
--- configure.ac (revision 113241)
+++ configure.ac (working copy)
@@ -116,9 +116,18 @@ AC_CHECK_TOOL(AS, as)
AC_CHECK_TOOL(LD, ld)
AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, :)
-AC_CHECK_PROGS(JAR, [jar fastjar], false)
-if test "$JAR" = false; then
- AC_MSG_ERROR(jar program not found)
+AC_PROG_AWK
+AC_CHECK_PROGS([JAR], [jar fastjar], no)
+AC_PATH_PROG([ZIP], [zip], no)
+AC_PATH_PROG([UNZIP], [unzip], unzip)
+AM_CONDITIONAL(BASH_JAR, test "$JAR" = no)
+if test "$ZIP" = no; then
+ if test "$JAR" = no; then
+ AC_MSG_ERROR([cannot find neither zip nor jar, cannot continue])
+ fi
+else
+ # InfoZIP available, use the 'guaranteed' Bourne-shell JAR to build libjava
+ JAR='$(top_builddir)/scripts/jar'
fi
AC_PROG_INSTALL
@@ -1479,6 +1488,8 @@ include/Makefile
testsuite/Makefile
])
+AC_CONFIG_FILES([scripts/jar], [chmod +x scripts/jar])
+
AC_CONFIG_COMMANDS([default],
[# Only add multilib support code if we just rebuilt top-level Makefile.
case " $CONFIG_FILES " in
Index: scripts/jar.in
===================================================================
--- scripts/jar.in (revision 0)
+++ scripts/jar.in (revision 0)
@@ -0,0 +1,503 @@
+#! /bin/sh
+# Copyright (C) 2006 Free Software Foundation
+# Written by Paolo Bonzini.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 2 of the License,
+# or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# POSIX and NLS nuisances, taken from autoconf.
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+: ${ZIP=@ZIP@}
+: ${UNZIP=@UNZIP@}
+progname="$0"
+
+# Emit a usage message and exit with error status 1
+usage () {
+ cat >&2 <<EOF
+Usage: $0 {ctxu}[vfm0Mi@] [jar-file] [manifest-file] {[-C dir] files} ...
+Options:
+ -c create new archive
+ -t list table of contents for archive
+ -x extract named (or all) files from archive
+ -u update existing archive
+ -v generate verbose output on standard output
+ -f specify archive file name
+ -m include manifest information from specified manifest file
+ -0 store only; use no ZIP compression
+ -M do not create a manifest file for the entries
+ -i generate index information for the specified jar files
+ -@ instead of {[-C dir] files} ... accept one or more response files,
+ each containing one command-line argument
+ -C change to the specified directory and include the following file
+If any file is a directory then it is processed recursively.
+The manifest file name and the archive file name needs to be specified
+in the same order the 'm' and 'f' flags are specified.
+
+Example 1: to archive two class files into an archive called classes.jar:
+ jar cvf classes.jar Foo.class Bar.class
+Example 2: use an existing manifest file 'mymanifest' and archive all the
+ files in the foo/ directory into 'classes.jar':
+ jar cvfm classes.jar mymanifest -C foo/ .
+
+EOF
+ exit 1
+}
+
+# Emit an error message and exit with error status 1
+error () {
+ echo "$progname: $*" >&2
+ exit 1
+}
+
+# Usage: copy SRC DEST
+# Copy file SRC to directory DEST, which is the staging area of the jar file.
+# Fail if it is already present or if it is not a regular file.
+copy () {
+ if test -f "$1"; then
+ # A simple optimization. Optimistically assuming that ln will work
+ # cuts 60% of the run-time!
+ if ln "$1" "$2"/"$1" > /dev/null 2>&1; then
+ return 0
+ fi
+
+ if test -e "$2"/"$1"; then
+ error "$1": Duplicate entry.
+ fi
+ $mkdir_p "$2"/`dirname "$1"`
+ ln "$1" "$2"/"$1" > /dev/null 2>&1 || cp "$1" "$2"/"$1"
+ elif test -e "$1"; then
+ error "$1": Invalid file type.
+ else
+ error "$1": File not found.
+ fi
+}
+
+# Make a temporary directory and store its name in the JARTMP variable.
+make_tmp () {
+ if test -z "$JARTMP"; then
+ JARTMPSUFF=$$
+ test -z "$RANDOM" && RANDOM=7654
+ while :; do
+ JARTMP=/tmp/tmp-jar.$JARTMPSUFF
+ $mkdir_p $JARTMP 2>&1 && break
+ JARTMPSUFF=`expr \( $JARTMPSUFF + $RANDOM \) % 32768`
+ done
+
+ trap 'rm -rf $JARTMP' EXIT
+ fi
+}
+
+# Usage: make_manifest destfile kind [source-manifest]
+# Create a manifest file and store it in destfile. KIND can be "default",
+# or "user", in which case SOURCE-MANIFEST must be specified as well.
+make_manifest () {
+ $mkdir_p `dirname "$1"`
+ case $2 in
+ default)
+ cat > "$1" <<\EOF
+Manifest-Version: 1.0
+Created-By: @VERSION@
+
+EOF
+ ;;
+ user)
+ cp "$3" "$1"
+ ;;
+ esac
+}
+
+# Usage: set_var var [value]
+# Exit with an error if set_var was already called for the same VAR. Else
+# set the variable VAR to the value VALUE (or the empty value if no parameter
+# is given).
+set_var () {
+ if eval test x\$set_$1 = xset; then
+ error Incompatible or repeated options.
+ else
+ eval $1='"$2"'
+ eval set_$1=set
+ fi
+}
+
+# Process the arguments, including -C options, and copy the whole tree
+# to $JARTMP/files so that zip can be invoked later from there.
+make_files () {
+ change=false
+ if $process_response_files; then
+ if test $# = 0; then
+ while read arg; do
+ make_files_1 "$arg"
+ done
+ else
+ for infile
+ do
+ exec 5<&0
+ exec 0< $infile
+ while read arg; do
+ make_files_1 "$arg"
+ done
+ exec 0<&5
+ done
+ fi
+ else
+ for arg
+ do
+ make_files_1 "$arg"
+ done
+ fi
+ cd "$old_dir"
+}
+
+# Usage: make_files_1 ARG
+# Process one argument, ARG.
+make_files_1 () {
+ if $change; then
+ change=false
+ cd "$1" || exit 1
+ return
+ fi
+ case "$1" in
+ -C)
+ change=:
+ ;;
+ -C*)
+ cd `expr "$1" : '-C\(.*\)' `
+ return
+ ;;
+ *)
+ if test -d "$1"; then
+ $mkdir_p $JARTMP/files/"$1"
+ find "$1" | while read file; do
+ if test -d "$file"; then
+ $mkdir_p $JARTMP/files/"$file"
+ else
+ copy "$file" $JARTMP/files
+ fi
+ done
+ else
+ copy "$1" $JARTMP/files
+ fi
+ ;;
+ esac
+ cd "$old_dir"
+}
+
+# Same as "jar tf $1".
+jar_list () {
+ $UNZIP -l "$1" | \
+ sed '1,/^ ----/d;/^ ----/,$d;s/^ *[0-9]* ..-..-.. ..:.. //'
+}
+
+# Same as "jar tvf $1".
+jar_list_verbose () {
+ $UNZIP -l "$1" | \
+ @AWK@ 'BEGIN { yes = 0 }
+ /^ ----/ { yes = !yes; next }
+ yes {
+ size=$1
+ split ($2, d, "-")
+ split ($3, t, ":")
+ d[3] += (d[3] < 80) ? 2000 : 1900
+ timestamp=d[3] " " d[2] " " d[1] " " t[1] " " t[2] " 00"
+ gsub (/^ *[0-9]* ..-..-.. ..:.. /, "")
+ printf "%6d %s %s\n", size, strftime ("%+", mktime (timestamp)), $0
+ }'
+}
+
+# mkdir -p emulation based on the mkinstalldirs script.
+mkdir_p ()
+{
+ for file
+ do
+ case $file in
+ /*) pathcomp=/ ;;
+ *) pathcomp= ;;
+ esac
+ oIFS=$IFS
+ IFS=/
+ set fnord $file
+ shift
+ IFS=$oIFS
+
+ for d
+ do
+ test "x$d" = x && continue
+ pathcomp=$pathcomp$d
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ mkdir "$pathcomp" || lasterr=$?
+ test -d "$pathcomp" || errstatus=$lasterr
+ fi
+ pathcomp=$pathcomp/
+ done
+ done
+ return "$errstatus"
+}
+
+# Detect mkdir -p
+# On NextStep and OpenStep, the `mkdir' command does not
+# recognize any option. It will interpret all options as
+# directories to create, and then abort because `.' already
+# exists.
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ mkdir_p='mkdir -p'
+else
+ mkdir_p='mkdir_p'
+ test -d ./-p && rmdir ./-p
+ test -d ./--version && rmdir ./--version
+fi
+
+# Process the first command line option.
+case "$1" in
+ -*) commands=`echo X"$1" | sed 's/^X-//' ` ;;
+ *) commands="$1"
+esac
+shift
+
+# Operation to perform on the JAR file
+mode=unknown
+
+# First -C option on the command line
+cur_dir=.
+
+# Base directory for -C options
+old_dir=`pwd`
+# JAR file to operate on
+jarfile=
+
+# default for no {m,M} option, user for "m" option, none for "M" option
+manifest_kind=default
+
+# "-0" if the "0" option was given
+store=
+
+# true if the "v" option was given
+verbose=false
+
+# true if the non-standard "@" option was given
+process_response_files=false
+
+# An exec command if we need to redirect the zip/unzip commands' output
+out_redirect=:
+
+while test -n "$commands"; do
+ # Process a letter at a time
+ command=`expr "$commands" : '\(.\)'`
+ commands=`expr "$commands" : '.\(.*\)'`
+ case "$command" in
+ c)
+ set_var mode create
+ ;;
+ t)
+ set_var mode list
+ ;;
+ x)
+ set_var mode extract
+ ;;
+ u)
+ set_var mode update
+ ;;
+
+ f)
+ test $# = 0 && usage
+ # Multiple "f" options are accepted by Sun's JAR tool.
+ jarfile="$1"
+ test -z "$jarfile" && usage
+ shift
+ ;;
+ m)
+ test $# = 0 && usage
+ # Multiple "m" options are accepted by Sun's JAR tool, but
+ # M always overrides m.
+ test "$manifest_kind" = default && manifest_kind=user
+ manifest_file="$1"
+ test -z "$manifest_file" && usage
+ shift
+ ;;
+ 0)
+ store=-0
+ ;;
+ v)
+ verbose=:
+ ;;
+ i)
+ # Not yet implemented, and probably never will.
+ ;;
+ M)
+ manifest_kind=none
+ ;;
+ C)
+ test $# = 0 && usage
+ cur_dir="$1"
+ shift
+ ;;
+ @)
+ process_response_files=: ;;
+ *)
+ usage ;;
+ esac
+done
+
+set -e
+
+case "X$jarfile" in
+ X)
+ # Work on stdin/stdout. Messages go to stderr, and if we need an input
+ # JAR file we save it temporarily in the temporary directory.
+ make_tmp
+ $mkdir_p $JARTMP/out
+ jarfile=$JARTMP/out/tmp-stdin.jar
+ out_redirect='exec >&2'
+ case $mode in
+ update|extract|list)
+ if $process_response_files && test $# = 0; then
+ error Cannot use stdin for response file.
+ fi
+ cat > $JARTMP/out/tmp-stdin.jar
+ ;;
+ esac
+ ;;
+
+ X*/*)
+ # Make an absolute path.
+ dir=`dirname "$jarfile"`
+ jarfile=`cd $dir && pwd`/`basename "$jarfile"`
+ ;;
+
+ X*)
+ # Make an absolute path from a filename in the current directory.
+ jarfile=`pwd`/`basename "$jarfile"`
+ ;;
+esac
+
+# Perform a -C option if given right away.
+cd "$cur_dir"
+
+case $mode in
+ unknown)
+ usage
+ ;;
+
+ extract)
+ make_tmp
+
+ # Extract the list of files in the JAR file
+ jar_list "$jarfile" > $JARTMP/list
+
+ # If there are files on the command line, expand directories and skip -C
+ # command line arguments
+ for arg
+ do
+ $skip && skip=false && continue
+ case "$arg" in
+ -C) skip=: ;;
+ -C*) ;;
+ *)
+ escaped=`echo "$arg" | sed -n 's/[][.^$\*]/\\&/' `
+ grep -e "^list/" >> $JARTMP/chosen || :
+ grep -e "^list$" >> $JARTMP/chosen || :
+ esac
+ done
+ test -f $JARTMP/chosen || cp $JARTMP/list $JARTMP/chosen
+
+ # Really execute unzip
+ if $verbose; then
+ sort < $JARTMP/chosen | uniq | xargs $UNZIP -o "$jarfile" | \
+ sed -ne 's/^ creating/ created/p' -e 's/^ inflating/extracted/p'
+ else
+ sort < $JARTMP/chosen | uniq | xargs $UNZIP -o "$jarfile" > /dev/null
+ fi
+ ;;
+
+ create)
+ make_tmp
+ $mkdir_p $JARTMP/out
+ $mkdir_p $JARTMP/files
+
+ # Do not overwrite the JAR file if something goes wrong
+ tmp_jarfile=$JARTMP/out/`basename "$jarfile"`
+
+ # Prepare the files in the temporary directory. This is necessary to
+ # support -C and still save relative paths in the JAR file.
+ make_files "$@"
+ if test $manifest_kind != none; then
+ make_manifest $JARTMP/files/META-INF/MANIFEST.MF $manifest_kind $manifest_file
+ fi
+
+ # Really execute zip
+ if $verbose; then
+ (eval $out_redirect; cd $JARTMP/files && $ZIP -rv "$tmp_jarfile" $store .)
+ else
+ (cd "$JARTMP/files" && $ZIP -r "$tmp_jarfile" $store . > /dev/null)
+ fi
+ test "$jarfile" = "$tmp_jarfile" || mv "$tmp_jarfile" "$jarfile"
+ ;;
+
+ update)
+ make_tmp
+ $mkdir_p $JARTMP/files
+ make_files "$@"
+
+ # Same as above, but zip takes care of not overwriting the file
+ case $manifest_kind in
+ none)
+ $verbose && (eval $out_redirect; echo removing manifest)
+ $ZIP -d "$jarfile" META-INF/MANIFEST.MF > /dev/null 2>&1 || :
+ ;;
+ *)
+ make_manifest $JARTMP/files/META-INF/MANIFEST.MF $manifest_kind $manifest_file
+ ;;
+ esac
+ if $verbose; then
+ (eval $out_redirect; cd $JARTMP/files && $ZIP -ruv "$jarfile" $store .)
+ else
+ (cd $JARTMP/files && $ZIP -ru "$jarfile" $store . > /dev/null)
+ fi
+ ;;
+
+ list)
+ # Everything's done in the functions
+ if $verbose; then
+ jar_list_verbose "$jarfile"
+ else
+ jar_list "$jarfile"
+ fi ;;
+esac
+
+if test "$out_redirect" != :; then
+ # Cat back to stdout if necessary
+ case $mode in
+ create|update) cat $JARTMP/out/tmp-stdin.jar ;;
+ esac
+fi
+exit 0