re PR middle-end/50260 (internal compiler error: Segmentation fault at ../../gcc...
[gcc.git] / libjava / scripts / jar.in
1 #! @SHELL@
2 # Copyright (C) 2006 Free Software Foundation
3 # Written by Paolo Bonzini.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published
7 # by the Free Software Foundation; either version 2 of the License,
8 # or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 # for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19
20 # POSIX and NLS nuisances, taken from autoconf.
21 if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
22 emulate sh
23 NULLCMD=:
24 # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
25 # is contrary to our usage. Disable this feature.
26 alias -g '${1+"$@"}'='"$@"'
27 setopt NO_GLOB_SUBST
28 else
29 case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
30 fi
31 BIN_SH=xpg4; export BIN_SH # for Tru64
32 DUALCASE=1; export DUALCASE # for MKS sh
33
34 if test "${LANG+set}" = set; then LANG=C; export LANG; fi
35 if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
36 if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
37 if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
38
39 # Also make sure CDPATH is empty, and IFS is space, tab, \n in that order.
40 # Be careful to avoid that editors munge IFS
41 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
42 IFS=" "" ""
43 "
44
45 : ${TMPDIR=/tmp}
46 : ${ZIP="@ZIP@"}
47 : ${UNZIP="@UNZIP@"}
48 progname="$0"
49
50 # Emit a usage message and exit with error status 1
51 usage () {
52 cat >&2 <<EOF
53 Usage: $0 {ctxu}[vfm0Mi@] [jar-file] [manifest-file] {[-C dir] files} ...
54 Options:
55 -c create new archive
56 -t list table of contents for archive
57 -x extract named (or all) files from archive
58 -u update existing archive
59 -v generate verbose output on standard output
60 -f specify archive file name
61 -m include manifest information from specified manifest file
62 -0 store only; use no ZIP compression
63 -M do not create a manifest file for the entries
64 -i generate index information for the specified jar files
65 -@ instead of {[-C dir] files} ... accept one or more response files,
66 each containing one command-line argument
67 -C change to the specified directory and include the following file
68 If any file is a directory then it is processed recursively.
69 The manifest file name and the archive file name needs to be specified
70 in the same order the 'm' and 'f' flags are specified.
71
72 Example 1: to archive two class files into an archive called classes.jar:
73 jar cvf classes.jar Foo.class Bar.class
74 Example 2: use an existing manifest file 'mymanifest' and archive all the
75 files in the foo/ directory into 'classes.jar':
76 jar cvfm classes.jar mymanifest -C foo/ .
77
78 EOF
79 (exit 1); exit 1
80 }
81
82 # Emit an error message and exit with error status 1
83 error () {
84 echo "$progname: $*" >&2
85 (exit 1); exit 1
86 }
87
88 # Usage: copy SRC DEST
89 # Copy file SRC to directory DEST, which is the staging area of the jar file.
90 # Fail if it is already present or if it is not a regular file.
91 copy () {
92 if test -f "$1"; then
93 # A simple optimization. Optimistically assuming that ln will work
94 # cuts 60% of the run-time!
95 if ln "$1" "$2"/"$1" > /dev/null 2>&1; then
96 return 0
97 fi
98
99 if test -f "$2"/"$1"; then
100 error "$1": Duplicate entry.
101 fi
102 dir=`dirname "$1"`
103 $mkdir_p "$2"/"$dir"
104 ln "$1" "$2"/"$1" > /dev/null 2>&1 || cp "$1" "$2"/"$1"
105 elif test -e "$1"; then
106 error "$1": Invalid file type.
107 else
108 error "$1": File not found.
109 fi
110 }
111
112 # Make a temporary directory and store its name in the JARTMP variable.
113 make_tmp () {
114 test -n "$JARTMP" && return
115
116 {
117 JARTMP=`(umask 077 && mktemp -d "$TMPDIR/jarXXXXXX") 2>/dev/null` &&
118 test -n "$JARTMP" && test -d "$JARTMP"
119 } || {
120 JARTMP=$TMPDIR/jar$$-$RANDOM
121 (umask 077 && mkdir "$JARTMP")
122 } || exit $?
123
124 trap 'exit_status=$?
125 if test -n "$JARTMP"; then rm -rf "$JARTMP"; fi
126 exit $exit_status' 0
127 }
128
129 # Usage: make_manifest destfile kind [source-manifest]
130 # Create a manifest file and store it in destfile. KIND can be "default",
131 # or "user", in which case SOURCE-MANIFEST must be specified as well.
132 make_manifest () {
133 dir=`dirname "$1"`
134 $mkdir_p "$dir"
135 case $2 in
136 default)
137 cat > "$1" <<\EOF
138 Manifest-Version: 1.0
139 Created-By: @VERSION@
140
141 EOF
142 ;;
143 user)
144 cp "$3" "$1"
145 ;;
146 esac
147 }
148
149 # Usage: set_var var [value]
150 # Exit with an error if set_var was already called for the same VAR. Else
151 # set the variable VAR to the value VALUE (or the empty value if no parameter
152 # is given).
153 set_var () {
154 if eval test x\$set_$1 = xset; then
155 error Incompatible or repeated options.
156 else
157 eval $1=\$2
158 eval set_$1=set
159 fi
160 }
161
162 # Process the arguments, including -C options, and copy the whole tree
163 # to $JARTMP/files so that zip can be invoked later from there.
164 make_files () {
165 change=false
166 if $process_response_files; then
167 if test $# = 0; then
168 while read arg; do
169 make_files_1 "$arg"
170 done
171 else
172 for infile
173 do
174 exec 5<&0
175 exec 0< $infile
176 while read arg; do
177 make_files_1 "$arg"
178 done
179 exec 0<&5
180 exec 5<&-
181 done
182 fi
183 else
184 for arg
185 do
186 make_files_1 "$arg"
187 done
188 fi
189 cd "$old_dir"
190 }
191
192 # Usage: make_files_1 ARG
193 # Process one argument, ARG.
194 make_files_1 () {
195 if $change; then
196 change=false
197 if cd "$1"; then
198 return
199 else
200 (exit 1); exit 1
201 fi
202 fi
203 case "$1" in
204 -C)
205 change=:
206 ;;
207 -C*)
208 cd `expr "$1" : '-C\(.*\)' `
209 return
210 ;;
211 *)
212 if test -d "$1"; then
213 $mkdir_p "$JARTMP"/files/"$1"
214 find "$1" | while read file; do
215 if test -d "$file"; then
216 $mkdir_p "$JARTMP"/files/"$file"
217 else
218 copy "$file" "$JARTMP"/files
219 fi
220 done
221 else
222 copy "$1" "$JARTMP"/files
223 fi
224 ;;
225 esac
226 cd "$old_dir"
227 }
228
229 # Same as "jar tf $1".
230 jar_list () {
231 $UNZIP -l "$1" | \
232 sed '1,/^ ----/d;/^ ----/,$d;s/^ *[0-9]* ..-..-.. ..:.. //'
233 }
234
235 # Same as "jar tvf $1".
236 jar_list_verbose () {
237 $UNZIP -l "$1" | \
238 @AWK@ 'BEGIN { yes = 0 }
239 /^ ----/ { yes = !yes; next }
240 yes {
241 size=$1
242 split ($2, d, "-")
243 split ($3, t, ":")
244 d[3] += (d[3] < 80) ? 2000 : 1900
245 timestamp=d[3] " " d[1] " " d[2] " " t[1] " " t[2] " 00"
246 gsub (/^ *[0-9]* ..-..-.. ..:.. /, "")
247 printf "%6d %s %s\n", size, strftime ("%a %b %d %H:%M:%S %Z %Y", mktime (timestamp)), $0
248 }'
249 }
250
251 # mkdir -p emulation based on the mkinstalldirs script.
252 func_mkdir_p () {
253 for file
254 do
255 case $file in
256 /*) pathcomp=/ ;;
257 *) pathcomp= ;;
258 esac
259 oIFS=$IFS
260 IFS=/
261 set fnord $file
262 shift
263 IFS=$oIFS
264
265 errstatus=0
266 for d
267 do
268 test "x$d" = x && continue
269 pathcomp=$pathcomp$d
270 case $pathcomp in
271 -*) pathcomp=./$pathcomp ;;
272 esac
273
274 if test ! -d "$pathcomp"; then
275 mkdir "$pathcomp" || lasterr=$?
276 test -d "$pathcomp" || errstatus=$lasterr
277 fi
278 pathcomp=$pathcomp/
279 done
280 done
281 return "$errstatus"
282 }
283
284 # Detect mkdir -p
285 # On NextStep and OpenStep, the `mkdir' command does not
286 # recognize any option. It will interpret all options as
287 # directories to create, and then abort because `.' already
288 # exists.
289 if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
290 mkdir_p='mkdir -p'
291 else
292 mkdir_p='func_mkdir_p'
293 test -d ./-p && rmdir ./-p
294 test -d ./--version && rmdir ./--version
295 fi
296
297 # Process the first command line option.
298 case "$1" in
299 -*) commands=`echo X"$1" | sed 's/^X-//' ` ;;
300 *) commands="$1"
301 esac
302 shift
303
304 # Operation to perform on the JAR file
305 mode=unknown
306
307 # First -C option on the command line
308 cur_dir=.
309
310 # Base directory for -C options
311 old_dir=`pwd`
312 # JAR file to operate on
313 jarfile=
314
315 # default for no {m,M} option, user for "m" option, none for "M" option
316 manifest_kind=default
317
318 # "-0" if the "0" option was given
319 store=
320
321 # true if the "v" option was given
322 verbose=false
323
324 # true if the non-standard "@" option was given
325 process_response_files=false
326
327 # An exec command if we need to redirect the zip/unzip commands' output
328 out_redirect=:
329
330 while test -n "$commands"; do
331 # Process a letter at a time
332 command=`expr "$commands" : '\(.\)'`
333 commands=`expr "$commands" : '.\(.*\)'`
334 case "$command" in
335 c)
336 set_var mode create
337 ;;
338 t)
339 set_var mode list
340 ;;
341 x)
342 set_var mode extract
343 ;;
344 u)
345 set_var mode update
346 ;;
347
348 f)
349 test $# = 0 && usage
350 # Multiple "f" options are accepted by Sun's JAR tool.
351 jarfile="$1"
352 test -z "$jarfile" && usage
353 shift
354 ;;
355 m)
356 test $# = 0 && usage
357 # Multiple "m" options are accepted by Sun's JAR tool, but
358 # M always overrides m.
359 test "$manifest_kind" = default && manifest_kind=user
360 manifest_file="$1"
361 test -z "$manifest_file" && usage
362 shift
363 ;;
364 0)
365 store=-0
366 ;;
367 v)
368 verbose=:
369 ;;
370 i)
371 # Not yet implemented, and probably never will.
372 ;;
373 M)
374 manifest_kind=none
375 ;;
376 C)
377 test $# = 0 && usage
378 cur_dir="$1"
379 shift
380 ;;
381 @)
382 process_response_files=: ;;
383 *)
384 usage ;;
385 esac
386 done
387
388 set -e
389
390 case "X$jarfile" in
391 X)
392 # Work on stdin/stdout. Messages go to stderr, and if we need an input
393 # JAR file we save it temporarily in the temporary directory.
394 make_tmp
395 $mkdir_p "$JARTMP"/out
396 jarfile="$JARTMP"/out/tmp-stdin.jar
397 out_redirect='exec >&2'
398 case $mode in
399 update|extract|list)
400 if $process_response_files && test $# = 0; then
401 error Cannot use stdin for response file.
402 fi
403 cat > "$JARTMP"/out/tmp-stdin.jar
404 ;;
405 esac
406 ;;
407
408 X*/*)
409 # Make an absolute path.
410 dir=`dirname "$jarfile"`
411 jarfile=`cd $dir && pwd`/`basename "$jarfile"`
412 ;;
413
414 X*)
415 # Make an absolute path from a filename in the current directory.
416 jarfile=`pwd`/`basename "$jarfile"`
417 ;;
418 esac
419
420 # Perform a -C option if given right away.
421 cd "$cur_dir"
422
423 case $mode in
424 unknown)
425 usage
426 ;;
427
428 extract)
429 make_tmp
430
431 # Extract the list of files in the JAR file
432 jar_list "$jarfile" > "$JARTMP"/list
433
434 # If there are files on the command line, expand directories and skip -C
435 # command line arguments
436 for arg
437 do
438 if $skip; then
439 skip=false
440 continue
441 fi
442 case "$arg" in
443 -C) skip=: ;;
444 -C*) ;;
445 *)
446 escaped=`echo "X$arg" | sed 's/^X//; s/[].[^$\\*]/\\\\&/g' `
447 grep "^$escaped/" "$JARTMP"/list >> "$JARTMP"/chosen || :
448 grep "^$escaped\$" "$JARTMP"/list >> "$JARTMP"/chosen || :
449 esac
450 done
451 test -f "$JARTMP"/chosen || cp "$JARTMP"/list "$JARTMP"/chosen
452
453 # Really execute unzip
454 if $verbose; then
455 sort < "$JARTMP"/chosen | uniq | xargs $UNZIP -o "$jarfile" | \
456 sed -ne 's/^ creating/ created/p' -e 's/^ inflating/extracted/p'
457 else
458 sort < "$JARTMP"/chosen | uniq | xargs $UNZIP -o "$jarfile" > /dev/null
459 fi
460 ;;
461
462 create)
463 make_tmp
464 $mkdir_p "$JARTMP"/out
465 $mkdir_p "$JARTMP"/files
466
467 # Do not overwrite the JAR file if something goes wrong
468 tmp_jarfile="$JARTMP"/out/`basename "$jarfile"`
469
470 # Prepare the files in the temporary directory. This is necessary to
471 # support -C and still save relative paths in the JAR file.
472 make_files ${1+"$@"}
473 if test $manifest_kind != none; then
474 make_manifest "$JARTMP"/files/META-INF/MANIFEST.MF $manifest_kind "$manifest_file"
475 fi
476
477 # Really execute zip
478 if $verbose; then
479 (eval $out_redirect; cd "$JARTMP"/files && $ZIP -rv "$tmp_jarfile" $store .)
480 else
481 (cd "$JARTMP/files" && $ZIP -r "$tmp_jarfile" $store . > /dev/null)
482 fi
483 test "$jarfile" = "$tmp_jarfile" || mv "$tmp_jarfile" "$jarfile"
484 ;;
485
486 update)
487 make_tmp
488 $mkdir_p "$JARTMP"/files
489 make_files ${1+"$@"}
490
491 # Same as above, but zip takes care of not overwriting the file
492 case $manifest_kind in
493 none)
494 $verbose && (eval $out_redirect; echo removing manifest)
495 $ZIP -d "$jarfile" META-INF/MANIFEST.MF > /dev/null 2>&1 || :
496 ;;
497 *)
498 make_manifest "$JARTMP"/files/META-INF/MANIFEST.MF $manifest_kind "$manifest_file"
499 ;;
500 esac
501 if $verbose; then
502 (eval $out_redirect; cd "$JARTMP"/files && $ZIP -ruv "$jarfile" $store .)
503 else
504 (cd "$JARTMP"/files && $ZIP -ru "$jarfile" $store . > /dev/null)
505 fi
506 ;;
507
508 list)
509 # Everything's done in the functions
510 if $verbose; then
511 jar_list_verbose "$jarfile"
512 else
513 jar_list "$jarfile"
514 fi ;;
515 esac
516
517 if test "$out_redirect" != :; then
518 # Cat back to stdout if necessary
519 case $mode in
520 create|update) cat "$JARTMP"/out/tmp-stdin.jar ;;
521 esac
522 fi
523 exit 0