xref: /aoo42x/main/solenv/bin/deliver.pl (revision cdf0e10c)
1*cdf0e10cSrcweir:
2*cdf0e10cSrcweireval 'exec perl -wS $0 ${1+"$@"}'
3*cdf0e10cSrcweir    if 0;
4*cdf0e10cSrcweir#*************************************************************************
5*cdf0e10cSrcweir#
6*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7*cdf0e10cSrcweir#
8*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates.
9*cdf0e10cSrcweir#
10*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite
11*cdf0e10cSrcweir#
12*cdf0e10cSrcweir# This file is part of OpenOffice.org.
13*cdf0e10cSrcweir#
14*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify
15*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3
16*cdf0e10cSrcweir# only, as published by the Free Software Foundation.
17*cdf0e10cSrcweir#
18*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful,
19*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of
20*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details
22*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code).
23*cdf0e10cSrcweir#
24*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License
25*cdf0e10cSrcweir# version 3 along with OpenOffice.org.  If not, see
26*cdf0e10cSrcweir# <http://www.openoffice.org/license.html>
27*cdf0e10cSrcweir# for a copy of the LGPLv3 License.
28*cdf0e10cSrcweir#
29*cdf0e10cSrcweir#*************************************************************************
30*cdf0e10cSrcweir
31*cdf0e10cSrcweir#
32*cdf0e10cSrcweir# deliver.pl - copy from module output tree to solver
33*cdf0e10cSrcweir#
34*cdf0e10cSrcweir
35*cdf0e10cSrcweiruse Cwd;
36*cdf0e10cSrcweiruse File::Basename;
37*cdf0e10cSrcweiruse File::Copy;
38*cdf0e10cSrcweiruse File::DosGlob 'glob';
39*cdf0e10cSrcweiruse File::Path;
40*cdf0e10cSrcweiruse File::Spec;
41*cdf0e10cSrcweir
42*cdf0e10cSrcweir#### script id #####
43*cdf0e10cSrcweir
44*cdf0e10cSrcweir( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/;
45*cdf0e10cSrcweir
46*cdf0e10cSrcweir$id_str = ' $Revision: 275594 $ ';
47*cdf0e10cSrcweir$id_str =~ /Revision:\s+(\S+)\s+\$/
48*cdf0e10cSrcweir  ? ($script_rev = $1) : ($script_rev = "-");
49*cdf0e10cSrcweir
50*cdf0e10cSrcweir
51*cdf0e10cSrcweir#### globals ####
52*cdf0e10cSrcweir
53*cdf0e10cSrcweir### valid actions ###
54*cdf0e10cSrcweir# if you add a action 'foo', than add 'foo' to this list and
55*cdf0e10cSrcweir# implement 'do_foo()' in the implemented actions area
56*cdf0e10cSrcweir@action_list        =   (           # valid actions
57*cdf0e10cSrcweir                        'copy',
58*cdf0e10cSrcweir                        'dos',
59*cdf0e10cSrcweir                        'addincpath',
60*cdf0e10cSrcweir                        'linklib',
61*cdf0e10cSrcweir                        'mkdir',
62*cdf0e10cSrcweir                        'symlink',
63*cdf0e10cSrcweir                        'touch'
64*cdf0e10cSrcweir                        );
65*cdf0e10cSrcweir
66*cdf0e10cSrcweir# copy filter: files matching these patterns won't be copied by
67*cdf0e10cSrcweir# the copy action
68*cdf0e10cSrcweir@copy_filter_patterns = (
69*cdf0e10cSrcweir                        );
70*cdf0e10cSrcweir
71*cdf0e10cSrcweir$strip              = '';
72*cdf0e10cSrcweir$is_debug           = 0;
73*cdf0e10cSrcweir
74*cdf0e10cSrcweir$error              = 0;
75*cdf0e10cSrcweir$module             = 0;            # module name
76*cdf0e10cSrcweir$repository         = 0;            # parent directory of this module
77*cdf0e10cSrcweir$base_dir           = 0;            # path to module base directory
78*cdf0e10cSrcweir$dlst_file          = 0;            # path to d.lst
79*cdf0e10cSrcweir$ilst_ext           = 'ilst';       # extension of image lists
80*cdf0e10cSrcweir$umask              = 22;           # default file/directory creation mask
81*cdf0e10cSrcweir$dest               = 0;            # optional destination path
82*cdf0e10cSrcweir$common_build       = 0;            # do we have common trees?
83*cdf0e10cSrcweir$common_dest        = 0;            # common tree on solver
84*cdf0e10cSrcweir
85*cdf0e10cSrcweir@action_data        = ();           # LoL with all action data
86*cdf0e10cSrcweir@macros             = ();           # d.lst macros
87*cdf0e10cSrcweir@addincpath_list    = ();           # files which have to be filtered through addincpath
88*cdf0e10cSrcweir@dirlist            = ();           # List of 'mkdir' targets
89*cdf0e10cSrcweir@zip_list           = ();           # files which have to be zipped
90*cdf0e10cSrcweir@common_zip_list    = ();           # common files which have to be zipped
91*cdf0e10cSrcweir@log_list           = ();           # LoL for logging all copy and link actions
92*cdf0e10cSrcweir@common_log_list    = ();           # LoL for logging all copy and link actions in common_dest
93*cdf0e10cSrcweir$logfiledate        = 0;            # Make log file as old as newest delivered file
94*cdf0e10cSrcweir$commonlogfiledate  = 0;            # Make log file as old as newest delivered file
95*cdf0e10cSrcweir
96*cdf0e10cSrcweir$files_copied       = 0;            # statistics
97*cdf0e10cSrcweir$files_unchanged    = 0;            # statistics
98*cdf0e10cSrcweir
99*cdf0e10cSrcweir$opt_force          = 0;            # option force copy
100*cdf0e10cSrcweir$opt_check          = 0;            # do actually execute any action
101*cdf0e10cSrcweir$opt_zip            = 0;            # create an additional zip file
102*cdf0e10cSrcweir$opt_silent         = 0;            # be silent, only report errors
103*cdf0e10cSrcweir$opt_verbose        = 0;            # be verbose (former default behaviour)
104*cdf0e10cSrcweir$opt_log            = 1;            # create an additional log file
105*cdf0e10cSrcweir$opt_link           = 0;            # hard link files into the solver to save disk space
106*cdf0e10cSrcweir$opt_deloutput      = 0;            # delete the output tree for the project once successfully delivered
107*cdf0e10cSrcweir$opt_checkdlst      = 0;
108*cdf0e10cSrcweir$delete_common      = 1;            # for "-delete": if defined delete files from common tree also
109*cdf0e10cSrcweir
110*cdf0e10cSrcweirif ($^O ne 'cygwin') {              # iz59477 - cygwin needes a dot "." at the end of filenames to disable
111*cdf0e10cSrcweir    $maybedot     = '';             # some .exe transformation magic.
112*cdf0e10cSrcweir} else {
113*cdf0e10cSrcweir    my $cygvernum = `uname -r`;
114*cdf0e10cSrcweir    my @cygvernum = split( /\./, $cygvernum);
115*cdf0e10cSrcweir    $cygvernum = shift @cygvernum;
116*cdf0e10cSrcweir    $cygvernum .= shift @cygvernum;
117*cdf0e10cSrcweir    if ( $cygvernum < 17 ) {
118*cdf0e10cSrcweir        $maybedot     = '.';
119*cdf0e10cSrcweir    } else {
120*cdf0e10cSrcweir        $maybedot     = '';               # no longer works with cygwin 1.7. other magic below.
121*cdf0e10cSrcweir    }
122*cdf0e10cSrcweir}
123*cdf0e10cSrcweir
124*cdf0e10cSrcweir($gui		= lc($ENV{GUI})) 		|| die "Can't determine 'GUI'. Please set environment.\n";
125*cdf0e10cSrcweir$tempcounter        = 0;
126*cdf0e10cSrcweir
127*cdf0e10cSrcweir# zip is default for RE master builds
128*cdf0e10cSrcweir$opt_zip = 1 if ( defined($ENV{DELIVER_TO_ZIP}) && uc($ENV{DELIVER_TO_ZIP}) eq 'TRUE' && ! defined($ENV{CWS_WORK_STAMP}));
129*cdf0e10cSrcweir
130*cdf0e10cSrcweir$has_symlinks       = 0;            # system supports symlinks
131*cdf0e10cSrcweir
132*cdf0e10cSrcweirfor (@action_list) {
133*cdf0e10cSrcweir    $action_hash{$_}++;
134*cdf0e10cSrcweir}
135*cdf0e10cSrcweir
136*cdf0e10cSrcweir# trap normal signals (HUP, INT, PIPE, TERM)
137*cdf0e10cSrcweir# for clean up on unexpected termination
138*cdf0e10cSrcweiruse sigtrap 'handler' => \&cleanup_and_die, 'normal-signals';
139*cdf0e10cSrcweir
140*cdf0e10cSrcweir#### main ####
141*cdf0e10cSrcweir
142*cdf0e10cSrcweirparse_options();
143*cdf0e10cSrcweir
144*cdf0e10cSrcweirprint "$script_name -- version: $script_rev\n" if !$opt_silent;
145*cdf0e10cSrcweir
146*cdf0e10cSrcweirif ( ! $opt_delete ) {
147*cdf0e10cSrcweir    if ( $ENV{GUI} eq 'WNT' ) {
148*cdf0e10cSrcweir        if ($ENV{COM} eq 'GCC') {
149*cdf0e10cSrcweir            initialize_strip() ;
150*cdf0e10cSrcweir        };
151*cdf0e10cSrcweir    } else {
152*cdf0e10cSrcweir        initialize_strip();
153*cdf0e10cSrcweir    }
154*cdf0e10cSrcweir}
155*cdf0e10cSrcweir
156*cdf0e10cSrcweirinit_globals();
157*cdf0e10cSrcweirpush_default_actions();
158*cdf0e10cSrcweirparse_dlst();
159*cdf0e10cSrcweircheck_dlst() if $opt_checkdlst;
160*cdf0e10cSrcweirwalk_action_data();
161*cdf0e10cSrcweirwalk_addincpath_list();
162*cdf0e10cSrcweirwrite_log() if $opt_log;
163*cdf0e10cSrcweirzip_files() if $opt_zip;
164*cdf0e10cSrcweircleanup() if $opt_delete;
165*cdf0e10cSrcweirdelete_output() if $opt_deloutput;
166*cdf0e10cSrcweirprint_stats();
167*cdf0e10cSrcweir
168*cdf0e10cSrcweirexit($error);
169*cdf0e10cSrcweir
170*cdf0e10cSrcweir#### implemented actions #####
171*cdf0e10cSrcweir
172*cdf0e10cSrcweirsub do_copy
173*cdf0e10cSrcweir{
174*cdf0e10cSrcweir    # We need to copy two times:
175*cdf0e10cSrcweir    # from the platform dependent output tree
176*cdf0e10cSrcweir    # and from the common output tree
177*cdf0e10cSrcweir    my ($dependent, $common, $from, $to, $file_list);
178*cdf0e10cSrcweir    my $line = shift;
179*cdf0e10cSrcweir    my $touch = 0;
180*cdf0e10cSrcweir
181*cdf0e10cSrcweir    $dependent = expand_macros($line);
182*cdf0e10cSrcweir    ($from, $to) = split(' ', $dependent);
183*cdf0e10cSrcweir    print "copy dependent: from: $from, to: $to\n" if $is_debug;
184*cdf0e10cSrcweir    glob_and_copy($from, $to, $touch);
185*cdf0e10cSrcweir
186*cdf0e10cSrcweir    if ($delete_common && $common_build && ( $line !~ /%COMMON_OUTDIR%/ ) ) {
187*cdf0e10cSrcweir        $line =~ s/%__SRC%/%COMMON_OUTDIR%/ig;
188*cdf0e10cSrcweir        if ( $line =~ /%COMMON_OUTDIR%/ ) {
189*cdf0e10cSrcweir            $line =~ s/%_DEST%/%COMMON_DEST%/ig;
190*cdf0e10cSrcweir            $common = expand_macros($line);
191*cdf0e10cSrcweir            ($from, $to) = split(' ', $common);
192*cdf0e10cSrcweir            print "copy common: from: $from, to: $to\n" if $is_debug;
193*cdf0e10cSrcweir            glob_and_copy($from, $to, $touch);
194*cdf0e10cSrcweir        }
195*cdf0e10cSrcweir    }
196*cdf0e10cSrcweir}
197*cdf0e10cSrcweir
198*cdf0e10cSrcweirsub do_dos
199*cdf0e10cSrcweir{
200*cdf0e10cSrcweir    my $line = shift;
201*cdf0e10cSrcweir
202*cdf0e10cSrcweir    my $command = expand_macros($line);
203*cdf0e10cSrcweir    if ( $opt_check ) {
204*cdf0e10cSrcweir        print "DOS: $command\n";
205*cdf0e10cSrcweir    }
206*cdf0e10cSrcweir    else {
207*cdf0e10cSrcweir        # HACK: remove MACOSX stuff which is wrongly labled with dos
208*cdf0e10cSrcweir        # better: fix broken d.lst
209*cdf0e10cSrcweir        return if ( $command =~ /MACOSX/ );
210*cdf0e10cSrcweir        $command =~ s#/#\\#g if $^O eq 'MSWin32';
211*cdf0e10cSrcweir        system($command);
212*cdf0e10cSrcweir    }
213*cdf0e10cSrcweir}
214*cdf0e10cSrcweir
215*cdf0e10cSrcweirsub do_addincpath
216*cdf0e10cSrcweir{
217*cdf0e10cSrcweir    # just collect all addincpath files, actual filtering is done later
218*cdf0e10cSrcweir    my $line = shift;
219*cdf0e10cSrcweir    my ($from, $to);
220*cdf0e10cSrcweir    my @globbed_files = ();
221*cdf0e10cSrcweir
222*cdf0e10cSrcweir    $line = expand_macros($line);
223*cdf0e10cSrcweir    ($from, $to) = split(' ', $line);
224*cdf0e10cSrcweir
225*cdf0e10cSrcweir    push( @addincpath_list, @{glob_line($from, $to)});
226*cdf0e10cSrcweir}
227*cdf0e10cSrcweir
228*cdf0e10cSrcweirsub do_linklib
229*cdf0e10cSrcweir{
230*cdf0e10cSrcweir    my ($lib_base, $lib_major,$from_dir, $to_dir);
231*cdf0e10cSrcweir    my $lib = shift;
232*cdf0e10cSrcweir    my @globbed_files = ();
233*cdf0e10cSrcweir    my %globbed_hash = ();
234*cdf0e10cSrcweir
235*cdf0e10cSrcweir    print "linklib: $lib\n" if $is_debug;
236*cdf0e10cSrcweir    print "has symlinks\n" if ( $has_symlinks && $is_debug );
237*cdf0e10cSrcweir
238*cdf0e10cSrcweir    return unless $has_symlinks;
239*cdf0e10cSrcweir
240*cdf0e10cSrcweir    $from_dir = expand_macros('../%__SRC%/lib');
241*cdf0e10cSrcweir    $to_dir = expand_macros('%_DEST%/lib%_EXT%');
242*cdf0e10cSrcweir
243*cdf0e10cSrcweir    @globbed_files = glob("$from_dir/$lib");
244*cdf0e10cSrcweir
245*cdf0e10cSrcweir    if ( $#globbed_files == -1 ) {
246*cdf0e10cSrcweir       return;
247*cdf0e10cSrcweir    }
248*cdf0e10cSrcweir
249*cdf0e10cSrcweir    foreach $lib (@globbed_files) {
250*cdf0e10cSrcweir        $lib = basename($lib);
251*cdf0e10cSrcweir        if ( $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)\.(\d+)(\.(\d+))?$/
252*cdf0e10cSrcweir             || $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)$/ )
253*cdf0e10cSrcweir        {
254*cdf0e10cSrcweir           push(@{$globbed_hash{$1}}, $lib);
255*cdf0e10cSrcweir        }
256*cdf0e10cSrcweir        else {
257*cdf0e10cSrcweir            print_warning("invalid library name: $lib");
258*cdf0e10cSrcweir        }
259*cdf0e10cSrcweir    }
260*cdf0e10cSrcweir
261*cdf0e10cSrcweir    foreach $lib_base ( sort keys %globbed_hash ) {
262*cdf0e10cSrcweir        $lib = get_latest_patchlevel(@{$globbed_hash{$lib_base}});
263*cdf0e10cSrcweir
264*cdf0e10cSrcweir        if ( $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)\.(\d+)(\.(\d+))?$/ )
265*cdf0e10cSrcweir        {
266*cdf0e10cSrcweir            $lib_major = "$lib_base.$3";
267*cdf0e10cSrcweir            $long = 1;
268*cdf0e10cSrcweir        }
269*cdf0e10cSrcweir        else
270*cdf0e10cSrcweir        {
271*cdf0e10cSrcweir            # $lib =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)$/;
272*cdf0e10cSrcweir            $long = 0;
273*cdf0e10cSrcweir        }
274*cdf0e10cSrcweir
275*cdf0e10cSrcweir        if ( $opt_check ) {
276*cdf0e10cSrcweir            if ( $opt_delete ) {
277*cdf0e10cSrcweir                print "REMOVE: $to_dir/$lib_major\n" if $long;
278*cdf0e10cSrcweir                print "REMOVE: $to_dir/$lib_base\n";
279*cdf0e10cSrcweir            }
280*cdf0e10cSrcweir            else {
281*cdf0e10cSrcweir                print "LINKLIB: $to_dir/$lib -> $to_dir/$lib_major\n" if $long;
282*cdf0e10cSrcweir                print "LINKLIB: $to_dir/$lib -> $to_dir/$lib_base\n";
283*cdf0e10cSrcweir            }
284*cdf0e10cSrcweir        }
285*cdf0e10cSrcweir        else {
286*cdf0e10cSrcweir            if ( $opt_delete ) {
287*cdf0e10cSrcweir                print "REMOVE: $to_dir/$lib_major\n" if ($long && $opt_verbose);
288*cdf0e10cSrcweir                print "REMOVE: $to_dir/$lib_base\n" if $opt_verbose;
289*cdf0e10cSrcweir                unlink "$to_dir/$lib_major" if $long;
290*cdf0e10cSrcweir                unlink "$to_dir/$lib_base";
291*cdf0e10cSrcweir                if ( $opt_zip ) {
292*cdf0e10cSrcweir                    push_on_ziplist("$to_dir/$lib_major") if $long;
293*cdf0e10cSrcweir                    push_on_ziplist("$to_dir/$lib_base");
294*cdf0e10cSrcweir                }
295*cdf0e10cSrcweir                return;
296*cdf0e10cSrcweir            }
297*cdf0e10cSrcweir            my $symlib;
298*cdf0e10cSrcweir            my @symlibs;
299*cdf0e10cSrcweir            if ($long)
300*cdf0e10cSrcweir            {
301*cdf0e10cSrcweir                @symlibs = ("$to_dir/$lib_major", "$to_dir/$lib_base");
302*cdf0e10cSrcweir            }
303*cdf0e10cSrcweir            else
304*cdf0e10cSrcweir            {
305*cdf0e10cSrcweir                @symlibs = ("$to_dir/$lib_base");
306*cdf0e10cSrcweir            }
307*cdf0e10cSrcweir            # remove old symlinks
308*cdf0e10cSrcweir            unlink(@symlibs);
309*cdf0e10cSrcweir            foreach $symlib (@symlibs) {
310*cdf0e10cSrcweir                print "LINKLIB: $lib -> $symlib\n" if $opt_verbose;
311*cdf0e10cSrcweir                if ( !symlink("$lib", "$symlib") ) {
312*cdf0e10cSrcweir                    print_error("can't symlink $lib -> $symlib: $!",0);
313*cdf0e10cSrcweir                }
314*cdf0e10cSrcweir                else {
315*cdf0e10cSrcweir                    push_on_ziplist($symlib) if $opt_zip;
316*cdf0e10cSrcweir                    push_on_loglist("LINK", "$lib", "$symlib") if $opt_log;
317*cdf0e10cSrcweir                }
318*cdf0e10cSrcweir            }
319*cdf0e10cSrcweir        }
320*cdf0e10cSrcweir    }
321*cdf0e10cSrcweir}
322*cdf0e10cSrcweir
323*cdf0e10cSrcweirsub do_mkdir
324*cdf0e10cSrcweir{
325*cdf0e10cSrcweir    my $path = expand_macros(shift);
326*cdf0e10cSrcweir    # strip whitespaces from path name
327*cdf0e10cSrcweir    $path =~ s/\s$//;
328*cdf0e10cSrcweir    if (( ! $opt_delete ) && ( ! -d $path )) {
329*cdf0e10cSrcweir        if ( $opt_check ) {
330*cdf0e10cSrcweir            print "MKDIR: $path\n";
331*cdf0e10cSrcweir        } else {
332*cdf0e10cSrcweir            mkpath($path, 0, 0777-$umask);
333*cdf0e10cSrcweir            if ( ! -d $path ) {
334*cdf0e10cSrcweir                print_error("mkdir: could not create directory '$path'", 0);
335*cdf0e10cSrcweir            }
336*cdf0e10cSrcweir        }
337*cdf0e10cSrcweir    }
338*cdf0e10cSrcweir}
339*cdf0e10cSrcweir
340*cdf0e10cSrcweirsub do_symlink
341*cdf0e10cSrcweir{
342*cdf0e10cSrcweir    my $line = shift;
343*cdf0e10cSrcweir
344*cdf0e10cSrcweir    $line = expand_macros($line);
345*cdf0e10cSrcweir    ($from, $to) = split(' ',$line);
346*cdf0e10cSrcweir    my $fullfrom = $from;
347*cdf0e10cSrcweir    if ( dirname($from) eq dirname($to) ) {
348*cdf0e10cSrcweir        $from = basename($from);
349*cdf0e10cSrcweir    }
350*cdf0e10cSrcweir    elsif ( dirname($from) eq '.' ) {
351*cdf0e10cSrcweir        # nothing to do
352*cdf0e10cSrcweir    }
353*cdf0e10cSrcweir    else {
354*cdf0e10cSrcweir        print_error("symlink: link must be in the same directory as file",0);
355*cdf0e10cSrcweir        return 0;
356*cdf0e10cSrcweir    }
357*cdf0e10cSrcweir
358*cdf0e10cSrcweir    print "symlink: $from, to: $to\n" if $is_debug;
359*cdf0e10cSrcweir
360*cdf0e10cSrcweir    return unless $has_symlinks;
361*cdf0e10cSrcweir
362*cdf0e10cSrcweir    if ( $opt_check ) {
363*cdf0e10cSrcweir        if ( $opt_delete ) {
364*cdf0e10cSrcweir            print "REMOVE: $to\n";
365*cdf0e10cSrcweir        }
366*cdf0e10cSrcweir        else {
367*cdf0e10cSrcweir            print "SYMLINK $from -> $to\n";
368*cdf0e10cSrcweir        }
369*cdf0e10cSrcweir    }
370*cdf0e10cSrcweir    else {
371*cdf0e10cSrcweir        print "REMOVE: $to\n" if $opt_verbose;
372*cdf0e10cSrcweir        unlink $to;
373*cdf0e10cSrcweir        if ( $opt_delete ) {
374*cdf0e10cSrcweir            push_on_ziplist($to) if $opt_zip;
375*cdf0e10cSrcweir            return;
376*cdf0e10cSrcweir        }
377*cdf0e10cSrcweir        return unless -e $fullfrom;
378*cdf0e10cSrcweir        print "SYMLIB: $from -> $to\n" if $opt_verbose;
379*cdf0e10cSrcweir        if ( !symlink("$from", "$to") ) {
380*cdf0e10cSrcweir            print_error("can't symlink $from -> $to: $!",0);
381*cdf0e10cSrcweir        }
382*cdf0e10cSrcweir        else {
383*cdf0e10cSrcweir            push_on_ziplist($to) if $opt_zip;
384*cdf0e10cSrcweir            push_on_loglist("LINK", "$from", "$to") if $opt_log;
385*cdf0e10cSrcweir        }
386*cdf0e10cSrcweir    }
387*cdf0e10cSrcweir}
388*cdf0e10cSrcweir
389*cdf0e10cSrcweirsub do_touch
390*cdf0e10cSrcweir{
391*cdf0e10cSrcweir    my ($from, $to);
392*cdf0e10cSrcweir    my $line = shift;
393*cdf0e10cSrcweir    my $touch = 1;
394*cdf0e10cSrcweir
395*cdf0e10cSrcweir    $line = expand_macros($line);
396*cdf0e10cSrcweir    ($from, $to) = split(' ', $line);
397*cdf0e10cSrcweir    print "touch: $from, to: $to\n" if $is_debug;
398*cdf0e10cSrcweir    glob_and_copy($from, $to, $touch);
399*cdf0e10cSrcweir}
400*cdf0e10cSrcweir
401*cdf0e10cSrcweir#### subroutines #####
402*cdf0e10cSrcweir
403*cdf0e10cSrcweirsub parse_options
404*cdf0e10cSrcweir{
405*cdf0e10cSrcweir    my $arg;
406*cdf0e10cSrcweir    my $dontdeletecommon = 0;
407*cdf0e10cSrcweir    $opt_silent = 1 if ( defined $ENV{VERBOSE} && $ENV{VERBOSE} eq 'FALSE');
408*cdf0e10cSrcweir    $opt_verbose = 1 if ( defined $ENV{VERBOSE} && $ENV{VERBOSE} eq 'TRUE');
409*cdf0e10cSrcweir    while ( $arg = shift @ARGV ) {
410*cdf0e10cSrcweir        $arg =~ /^-force$/      and $opt_force  = 1  and next;
411*cdf0e10cSrcweir        $arg =~ /^-check$/      and $opt_check  = 1  and $opt_verbose = 1 and next;
412*cdf0e10cSrcweir        $arg =~ /^-quiet$/      and $opt_silent = 1  and next;
413*cdf0e10cSrcweir        $arg =~ /^-verbose$/    and $opt_verbose = 1 and next;
414*cdf0e10cSrcweir        $arg =~ /^-zip$/        and $opt_zip    = 1  and next;
415*cdf0e10cSrcweir        $arg =~ /^-delete$/     and $opt_delete = 1  and next;
416*cdf0e10cSrcweir        $arg =~ /^-dontdeletecommon$/ and $dontdeletecommon = 1 and next;
417*cdf0e10cSrcweir        $arg =~ /^-help$/       and $opt_help   = 1  and $arg = '';
418*cdf0e10cSrcweir        $arg =~ /^-link$/       and $ENV{GUI} ne 'WNT' and $opt_link = 1 and next;
419*cdf0e10cSrcweir        $arg =~ /^-deloutput$/  and $opt_deloutput = 1 and next;
420*cdf0e10cSrcweir        $arg =~ /^-debug$/      and $is_debug   = 1  and next;
421*cdf0e10cSrcweir        $arg =~ /^-checkdlst$/  and $opt_checkdlst = 1 and next;
422*cdf0e10cSrcweir        print_error("invalid option $arg") if ( $arg =~ /^-/ );
423*cdf0e10cSrcweir        if ( $arg =~ /^-/ || $opt_help || $#ARGV > -1 ) {
424*cdf0e10cSrcweir            usage(1);
425*cdf0e10cSrcweir        }
426*cdf0e10cSrcweir        $dest = $arg;
427*cdf0e10cSrcweir    }
428*cdf0e10cSrcweir    # $dest and $opt_zip or $opt_delete are mutually exclusive
429*cdf0e10cSrcweir    if ( $dest and ($opt_zip || $opt_delete) ) {
430*cdf0e10cSrcweir        usage(1);
431*cdf0e10cSrcweir    }
432*cdf0e10cSrcweir    # $opt_silent and $opt_check or $opt_verbose are mutually exclusive
433*cdf0e10cSrcweir    if ( ($opt_check or $opt_verbose) and $opt_silent ) {
434*cdf0e10cSrcweir        print STDERR "Error on command line: options '-check' and '-quiet' are mutually exclusive.\n";
435*cdf0e10cSrcweir        usage(1);
436*cdf0e10cSrcweir    }
437*cdf0e10cSrcweir    if ($dontdeletecommon) {
438*cdf0e10cSrcweir        if (!$opt_delete) {
439*cdf0e10cSrcweir            usage(1);
440*cdf0e10cSrcweir        }
441*cdf0e10cSrcweir        $delete_common = 0;
442*cdf0e10cSrcweir    };
443*cdf0e10cSrcweir    # $opt_delete implies $opt_force
444*cdf0e10cSrcweir    $opt_force = 1 if $opt_delete;
445*cdf0e10cSrcweir}
446*cdf0e10cSrcweir
447*cdf0e10cSrcweirsub init_globals
448*cdf0e10cSrcweir{
449*cdf0e10cSrcweir    my $ext;
450*cdf0e10cSrcweir    ($module, $repository, $base_dir, $dlst_file) =  get_base();
451*cdf0e10cSrcweir
452*cdf0e10cSrcweir    # for CWS:
453*cdf0e10cSrcweir    $module =~ s/\.lnk$//;
454*cdf0e10cSrcweir
455*cdf0e10cSrcweir    print "Module=$module, Base_Dir=$base_dir, d.lst=$dlst_file\n" if $is_debug;
456*cdf0e10cSrcweir
457*cdf0e10cSrcweir    $umask = umask();
458*cdf0e10cSrcweir    if ( !defined($umask) ) {
459*cdf0e10cSrcweir        $umask = 22;
460*cdf0e10cSrcweir    }
461*cdf0e10cSrcweir
462*cdf0e10cSrcweir    my $build_sosl    = $ENV{'BUILD_SOSL'};
463*cdf0e10cSrcweir    my $common_outdir = $ENV{'COMMON_OUTDIR'};
464*cdf0e10cSrcweir    my $inpath        = $ENV{'INPATH'};
465*cdf0e10cSrcweir    my $solarversion  = $ENV{'SOLARVERSION'};
466*cdf0e10cSrcweir    my $updater       = $ENV{'UPDATER'};
467*cdf0e10cSrcweir    my $updminor      = $ENV{'UPDMINOR'};
468*cdf0e10cSrcweir    my $updminorext   = $ENV{'UPDMINOREXT'};
469*cdf0e10cSrcweir    my $work_stamp    = $ENV{'WORK_STAMP'};
470*cdf0e10cSrcweir
471*cdf0e10cSrcweir    # special security check for release engineers
472*cdf0e10cSrcweir    if ( defined($updater) && !defined($build_sosl) && !$opt_force) {
473*cdf0e10cSrcweir        my $path = getcwd();
474*cdf0e10cSrcweir        if ( $path !~ /$work_stamp/io ) {
475*cdf0e10cSrcweir            print_error("can't deliver from local directory to SOLARVERSION");
476*cdf0e10cSrcweir            print STDERR "\nDANGER! Release Engineer:\n";
477*cdf0e10cSrcweir            print STDERR "do you really want to deliver from $path to SOLARVERSION?\n";
478*cdf0e10cSrcweir            print STDERR "If so, please use the -force switch\n\n";
479*cdf0e10cSrcweir            exit(7);
480*cdf0e10cSrcweir        }
481*cdf0e10cSrcweir    }
482*cdf0e10cSrcweir
483*cdf0e10cSrcweir    # do we have a valid environment?
484*cdf0e10cSrcweir    if ( !defined($inpath) ) {
485*cdf0e10cSrcweir            print_error("no environment", 0);
486*cdf0e10cSrcweir            exit(3);
487*cdf0e10cSrcweir    }
488*cdf0e10cSrcweir
489*cdf0e10cSrcweir    $ext = "";
490*cdf0e10cSrcweir    if ( ($updminor) && !$dest ) {
491*cdf0e10cSrcweir        $ext = "$updminorext";
492*cdf0e10cSrcweir    }
493*cdf0e10cSrcweir
494*cdf0e10cSrcweir    # Do we have common trees?
495*cdf0e10cSrcweir    if ( defined($ENV{'common_build'}) && $ENV{'common_build'} eq 'TRUE' ) {
496*cdf0e10cSrcweir        $common_build = 1;
497*cdf0e10cSrcweir        if ((defined $common_outdir) && ($common_outdir ne "")) {
498*cdf0e10cSrcweir            $common_outdir = $common_outdir . ".pro" if $inpath =~ /\.pro$/;
499*cdf0e10cSrcweir            if ( $dest ) {
500*cdf0e10cSrcweir                $common_dest = $dest;
501*cdf0e10cSrcweir            } else {
502*cdf0e10cSrcweir                $common_dest = "$solarversion/$common_outdir";
503*cdf0e10cSrcweir                $dest = "$solarversion/$inpath";
504*cdf0e10cSrcweir            }
505*cdf0e10cSrcweir        } else {
506*cdf0e10cSrcweir            print_error("common_build defined without common_outdir", 0);
507*cdf0e10cSrcweir            exit(6);
508*cdf0e10cSrcweir        }
509*cdf0e10cSrcweir    } else {
510*cdf0e10cSrcweir        $common_outdir = $inpath;
511*cdf0e10cSrcweir        $dest = "$solarversion/$inpath" if ( !$dest );
512*cdf0e10cSrcweir        $common_dest = $dest;
513*cdf0e10cSrcweir    }
514*cdf0e10cSrcweir    $dest =~ s#\\#/#g;
515*cdf0e10cSrcweir    $common_dest =~ s#\\#/#g;
516*cdf0e10cSrcweir
517*cdf0e10cSrcweir    # the following macros are obsolete, will be flagged as error
518*cdf0e10cSrcweir    # %__WORKSTAMP%
519*cdf0e10cSrcweir    # %GUIBASE%
520*cdf0e10cSrcweir    # %SDK%
521*cdf0e10cSrcweir    # %SOLARVER%
522*cdf0e10cSrcweir    # %__OFFENV%
523*cdf0e10cSrcweir    # %DLLSUFFIX%'
524*cdf0e10cSrcweir    # %OUTPATH%
525*cdf0e10cSrcweir    # %L10N_FRAMEWORK%
526*cdf0e10cSrcweir    # %UPD%
527*cdf0e10cSrcweir
528*cdf0e10cSrcweir    # valid macros
529*cdf0e10cSrcweir    @macros = (
530*cdf0e10cSrcweir                [ '%__PRJROOT%',        $base_dir       ],
531*cdf0e10cSrcweir                [ '%__SRC%',            $inpath         ],
532*cdf0e10cSrcweir                [ '%_DEST%',            $dest           ],
533*cdf0e10cSrcweir                [ '%_EXT%',             $ext            ],
534*cdf0e10cSrcweir                [ '%COMMON_OUTDIR%',    $common_outdir  ],
535*cdf0e10cSrcweir                [ '%COMMON_DEST%',      $common_dest    ],
536*cdf0e10cSrcweir                [ '%GUI%',              $gui            ]
537*cdf0e10cSrcweir              );
538*cdf0e10cSrcweir
539*cdf0e10cSrcweir    # find out if the system supports symlinks
540*cdf0e10cSrcweir    $has_symlinks = eval { symlink("",""); 1 };
541*cdf0e10cSrcweir}
542*cdf0e10cSrcweir
543*cdf0e10cSrcweirsub get_base
544*cdf0e10cSrcweir{
545*cdf0e10cSrcweir    # a module base dir contains a subdir 'prj'
546*cdf0e10cSrcweir    # which in turn contains a file 'd.lst'
547*cdf0e10cSrcweir    my (@field, $repo, $base, $dlst);
548*cdf0e10cSrcweir    my $path = getcwd();
549*cdf0e10cSrcweir
550*cdf0e10cSrcweir    @field = split(/\//, $path);
551*cdf0e10cSrcweir
552*cdf0e10cSrcweir    while ( $#field != -1 ) {
553*cdf0e10cSrcweir        $base = join('/', @field);
554*cdf0e10cSrcweir        $dlst = $base . '/prj/d.lst';
555*cdf0e10cSrcweir        last if -e $dlst;
556*cdf0e10cSrcweir        pop @field;
557*cdf0e10cSrcweir    }
558*cdf0e10cSrcweir
559*cdf0e10cSrcweir    if ( $#field == -1 ) {
560*cdf0e10cSrcweir        print_error("can't find d.lst");
561*cdf0e10cSrcweir        exit(2);
562*cdf0e10cSrcweir    }
563*cdf0e10cSrcweir    else {
564*cdf0e10cSrcweir        if ( defined $field[-2] ) {
565*cdf0e10cSrcweir            $repo = $field[-2];
566*cdf0e10cSrcweir        } else {
567*cdf0e10cSrcweir            print_error("Internal error: cannot determine module's parent directory");
568*cdf0e10cSrcweir        }
569*cdf0e10cSrcweir        return ($field[-1], $repo, $base, $dlst);
570*cdf0e10cSrcweir    }
571*cdf0e10cSrcweir}
572*cdf0e10cSrcweir
573*cdf0e10cSrcweirsub parse_dlst
574*cdf0e10cSrcweir{
575*cdf0e10cSrcweir    my $line_cnt = 0;
576*cdf0e10cSrcweir    open(DLST, "<$dlst_file") or die "can't open d.lst";
577*cdf0e10cSrcweir    while(<DLST>) {
578*cdf0e10cSrcweir        $line_cnt++;
579*cdf0e10cSrcweir        tr/\r\n//d;
580*cdf0e10cSrcweir        next if /^#/;
581*cdf0e10cSrcweir        next if /^\s*$/;
582*cdf0e10cSrcweir        if (!$delete_common && /%COMMON_DEST%/) {
583*cdf0e10cSrcweir            # Just ignore all lines with %COMMON_DEST%
584*cdf0e10cSrcweir            next;
585*cdf0e10cSrcweir        };
586*cdf0e10cSrcweir        if ( /^\s*(\w+?):\s+(.*)$/ ) {
587*cdf0e10cSrcweir            if ( !exists $action_hash{$1} ) {
588*cdf0e10cSrcweir                print_error("unknown action: \'$1\'", $line_cnt);
589*cdf0e10cSrcweir                exit(4);
590*cdf0e10cSrcweir            }
591*cdf0e10cSrcweir            push(@action_data, [$1, $2]);
592*cdf0e10cSrcweir        }
593*cdf0e10cSrcweir        else {
594*cdf0e10cSrcweir            if ( /^\s*%(COMMON)?_DEST%\\/ ) {
595*cdf0e10cSrcweir                # only copy from source dir to solver, not from solver to solver
596*cdf0e10cSrcweir                print_warning("illegal copy action, ignored: \'$_\'", $line_cnt);
597*cdf0e10cSrcweir                next;
598*cdf0e10cSrcweir            }
599*cdf0e10cSrcweir            push(@action_data, ['copy', $_]);
600*cdf0e10cSrcweir            # for each ressource file (.res) copy its image list (.ilst)
601*cdf0e10cSrcweir            if ( /\.res\s/ ) {
602*cdf0e10cSrcweir                my $imagelist = $_;
603*cdf0e10cSrcweir                $imagelist =~ s/\.res/\.$ilst_ext/g;
604*cdf0e10cSrcweir                $imagelist =~ s/\\bin%_EXT%\\/\\res%_EXT%\\img\\/;
605*cdf0e10cSrcweir                push(@action_data, ['copy', $imagelist]);
606*cdf0e10cSrcweir            }
607*cdf0e10cSrcweir        }
608*cdf0e10cSrcweir        # call expand_macros()just to find any undefined macros early
609*cdf0e10cSrcweir        # real expansion is done later
610*cdf0e10cSrcweir        expand_macros($_, $line_cnt);
611*cdf0e10cSrcweir    }
612*cdf0e10cSrcweir    close(DLST);
613*cdf0e10cSrcweir}
614*cdf0e10cSrcweir
615*cdf0e10cSrcweirsub expand_macros
616*cdf0e10cSrcweir{
617*cdf0e10cSrcweir    # expand all macros and change backslashes to slashes
618*cdf0e10cSrcweir    my $line        = shift;
619*cdf0e10cSrcweir    my $line_cnt    = shift;
620*cdf0e10cSrcweir    my $i;
621*cdf0e10cSrcweir
622*cdf0e10cSrcweir    for ($i=0; $i<=$#macros; $i++)  {
623*cdf0e10cSrcweir        $line =~ s/$macros[$i][0]/$macros[$i][1]/gi
624*cdf0e10cSrcweir    }
625*cdf0e10cSrcweir    if ( $line =~ /(%\w+%)/ ) {
626*cdf0e10cSrcweir        if ( $1 ne '%OS%' ) {   # %OS% looks like a macro but is not ...
627*cdf0e10cSrcweir            print_error("unknown/obsolete macro: \'$1\'", $line_cnt);
628*cdf0e10cSrcweir        }
629*cdf0e10cSrcweir    }
630*cdf0e10cSrcweir    $line =~ s#\\#/#g;
631*cdf0e10cSrcweir    return $line;
632*cdf0e10cSrcweir}
633*cdf0e10cSrcweir
634*cdf0e10cSrcweirsub walk_action_data
635*cdf0e10cSrcweir{
636*cdf0e10cSrcweir    # all actions have to be excuted relative to the prj directory
637*cdf0e10cSrcweir    chdir("$base_dir/prj");
638*cdf0e10cSrcweir    # dispatch depending on action type
639*cdf0e10cSrcweir    for (my $i=0; $i <= $#action_data; $i++) {
640*cdf0e10cSrcweir            &{"do_".$action_data[$i][0]}($action_data[$i][1]);
641*cdf0e10cSrcweir            if ( $action_data[$i][0] eq 'mkdir' ) {
642*cdf0e10cSrcweir                # fill array with (possibly) created directories in
643*cdf0e10cSrcweir                # revers order for removal in 'cleanup'
644*cdf0e10cSrcweir                unshift @dirlist, $action_data[$i][1];
645*cdf0e10cSrcweir            }
646*cdf0e10cSrcweir    }
647*cdf0e10cSrcweir}
648*cdf0e10cSrcweir
649*cdf0e10cSrcweirsub glob_line
650*cdf0e10cSrcweir{
651*cdf0e10cSrcweir    my $from = shift;
652*cdf0e10cSrcweir    my $to = shift;
653*cdf0e10cSrcweir    my $to_dir = shift;
654*cdf0e10cSrcweir    my $replace = 0;
655*cdf0e10cSrcweir    my @globbed_files = ();
656*cdf0e10cSrcweir
657*cdf0e10cSrcweir    if ( ! ( $from && $to ) ) {
658*cdf0e10cSrcweir        print_warning("Error in d.lst? source: '$from' destination: '$to'");
659*cdf0e10cSrcweir        return \@globbed_files;
660*cdf0e10cSrcweir    }
661*cdf0e10cSrcweir
662*cdf0e10cSrcweir    if ( $to =~ /[\*\?\[\]]/ ) {
663*cdf0e10cSrcweir        my $to_fname;
664*cdf0e10cSrcweir        ($to_fname, $to_dir) = fileparse($to);
665*cdf0e10cSrcweir        $replace = 1;
666*cdf0e10cSrcweir    }
667*cdf0e10cSrcweir
668*cdf0e10cSrcweir    if ( $from =~ /[\*\?\[\]]/ ) {
669*cdf0e10cSrcweir        # globbing necessary, no renaming possible
670*cdf0e10cSrcweir        my $file;
671*cdf0e10cSrcweir        my @file_list = glob($from);
672*cdf0e10cSrcweir
673*cdf0e10cSrcweir        foreach $file ( @file_list ) {
674*cdf0e10cSrcweir            next if ( -d $file); # we only copy files, not directories
675*cdf0e10cSrcweir            my ($fname, $dir) = fileparse($file);
676*cdf0e10cSrcweir            my $copy = ($replace) ? $to_dir . $fname : $to . '/' . $fname;
677*cdf0e10cSrcweir            push(@globbed_files, [$file, $copy]);
678*cdf0e10cSrcweir        }
679*cdf0e10cSrcweir    }
680*cdf0e10cSrcweir    else {
681*cdf0e10cSrcweir        # no globbing but renaming possible
682*cdf0e10cSrcweir        # #i89066#
683*cdf0e10cSrcweir        if (-d $to && -f $from) {
684*cdf0e10cSrcweir            my $filename = File::Basename::basename($from);
685*cdf0e10cSrcweir            $to .= '/' if ($to !~ /[\\|\/]$/);
686*cdf0e10cSrcweir            $to .= $filename;
687*cdf0e10cSrcweir        };
688*cdf0e10cSrcweir        push(@globbed_files, [$from, $to]);
689*cdf0e10cSrcweir    }
690*cdf0e10cSrcweir    if ( $opt_checkdlst ) {
691*cdf0e10cSrcweir        my $outtree = expand_macros("%__SRC%");
692*cdf0e10cSrcweir        my $commonouttree = expand_macros("%COMMON_OUTDIR%");
693*cdf0e10cSrcweir        if (( $from !~ /\Q$outtree\E/ ) && ( $from !~ /\Q$commonouttree\E/ )) {
694*cdf0e10cSrcweir            print_warning("'$from' does not match any file") if ( $#globbed_files == -1 );
695*cdf0e10cSrcweir        }
696*cdf0e10cSrcweir    }
697*cdf0e10cSrcweir    return \@globbed_files;
698*cdf0e10cSrcweir}
699*cdf0e10cSrcweir
700*cdf0e10cSrcweir
701*cdf0e10cSrcweirsub glob_and_copy
702*cdf0e10cSrcweir{
703*cdf0e10cSrcweir    my $from = shift;
704*cdf0e10cSrcweir    my $to = shift;
705*cdf0e10cSrcweir    my $touch = shift;
706*cdf0e10cSrcweir
707*cdf0e10cSrcweir    my @copy_files = @{glob_line($from, $to)};
708*cdf0e10cSrcweir
709*cdf0e10cSrcweir    for (my $i = 0; $i <= $#copy_files; $i++) {
710*cdf0e10cSrcweir        next if filter_out($copy_files[$i][0]); # apply copy filter
711*cdf0e10cSrcweir        copy_if_newer($copy_files[$i][0], $copy_files[$i][1], $touch)
712*cdf0e10cSrcweir                    ? $files_copied++ : $files_unchanged++;
713*cdf0e10cSrcweir    }
714*cdf0e10cSrcweir}
715*cdf0e10cSrcweir
716*cdf0e10cSrcweirsub is_unstripped {
717*cdf0e10cSrcweir    my $file_name = shift;
718*cdf0e10cSrcweir    my $nm_output;
719*cdf0e10cSrcweir
720*cdf0e10cSrcweir    if (-f $file_name.$maybedot) {
721*cdf0e10cSrcweir        my $file_type = `file $file_name`;
722*cdf0e10cSrcweir        # OS X file command doesn't know if a file is stripped or not
723*cdf0e10cSrcweir        if (($file_type =~ /not stripped/o) || ($file_type =~ /Mach-O/o) ||
724*cdf0e10cSrcweir            (($file_type =~ /PE/o) && ($ENV{GUI} eq 'WNT') &&
725*cdf0e10cSrcweir             ($nm_output = `nm $file_name 2>&1`) && $nm_output &&
726*cdf0e10cSrcweir             !($nm_output =~ /no symbols/i) && !($nm_output =~ /not recognized/i))) {
727*cdf0e10cSrcweir            return '1' if ($file_name =~ /\.bin$/o);
728*cdf0e10cSrcweir            return '1' if ($file_name =~ /\.so\.*/o);
729*cdf0e10cSrcweir            return '1' if ($file_name =~ /\.dylib\.*/o);
730*cdf0e10cSrcweir            return '1' if ($file_name =~ /\.com\.*/o);
731*cdf0e10cSrcweir            return '1' if ($file_name =~ /\.dll\.*/o);
732*cdf0e10cSrcweir            return '1' if ($file_name =~ /\.exe\.*/o);
733*cdf0e10cSrcweir            return '1' if (basename($file_name) !~ /\./o);
734*cdf0e10cSrcweir        }
735*cdf0e10cSrcweir    };
736*cdf0e10cSrcweir    return '';
737*cdf0e10cSrcweir}
738*cdf0e10cSrcweir
739*cdf0e10cSrcweirsub initialize_strip {
740*cdf0e10cSrcweir    if ((!defined $ENV{DISABLE_STRIP}) || ($ENV{DISABLE_STRIP} eq "")) {
741*cdf0e10cSrcweir        $strip .= 'guw ' if ($^O eq 'cygwin');
742*cdf0e10cSrcweir        $strip .= 'strip';
743*cdf0e10cSrcweir	    $strip .= " -x" if ($ENV{OS} eq 'MACOSX');
744*cdf0e10cSrcweir        $strip .= " -R '.comment' -s" if ($ENV{OS} eq 'LINUX');
745*cdf0e10cSrcweir    };
746*cdf0e10cSrcweir};
747*cdf0e10cSrcweir
748*cdf0e10cSrcweirsub is_jar {
749*cdf0e10cSrcweir    my $file_name = shift;
750*cdf0e10cSrcweir
751*cdf0e10cSrcweir    if (-f $file_name && (( `file $file_name` ) =~ /Zip archive/o)) {
752*cdf0e10cSrcweir        return '1' if ($file_name =~ /\.jar\.*/o);
753*cdf0e10cSrcweir    };
754*cdf0e10cSrcweir    return '';
755*cdf0e10cSrcweir}
756*cdf0e10cSrcweir
757*cdf0e10cSrcweirsub execute_system {
758*cdf0e10cSrcweir    my $command = shift;
759*cdf0e10cSrcweir    if (system($command)) {
760*cdf0e10cSrcweir        print_error("Failed to execute $command");
761*cdf0e10cSrcweir        exit($?);
762*cdf0e10cSrcweir    };
763*cdf0e10cSrcweir};
764*cdf0e10cSrcweir
765*cdf0e10cSrcweirsub strip_target {
766*cdf0e10cSrcweir    my $file = shift;
767*cdf0e10cSrcweir    my $temp_file = shift;
768*cdf0e10cSrcweir    $temp_file =~ s/\/{2,}/\//g;
769*cdf0e10cSrcweir    my $rc = copy($file, $temp_file);
770*cdf0e10cSrcweir    execute_system("$strip $temp_file");
771*cdf0e10cSrcweir    return $rc;
772*cdf0e10cSrcweir};
773*cdf0e10cSrcweir
774*cdf0e10cSrcweirsub copy_if_newer
775*cdf0e10cSrcweir{
776*cdf0e10cSrcweir    # return 0 if file is unchanged ( for whatever reason )
777*cdf0e10cSrcweir    # return 1 if file has been copied
778*cdf0e10cSrcweir    my $from = shift;
779*cdf0e10cSrcweir    my $to = shift;
780*cdf0e10cSrcweir    my $touch = shift;
781*cdf0e10cSrcweir    my $from_stat_ref;
782*cdf0e10cSrcweir    my $rc = 0;
783*cdf0e10cSrcweir
784*cdf0e10cSrcweir    print "testing $from, $to\n" if $is_debug;
785*cdf0e10cSrcweir    push_on_ziplist($to) if $opt_zip;
786*cdf0e10cSrcweir    push_on_loglist("COPY", "$from", "$to") if $opt_log;
787*cdf0e10cSrcweir    return 0 unless ($from_stat_ref = is_newer($from, $to, $touch));
788*cdf0e10cSrcweir
789*cdf0e10cSrcweir    if ( $opt_delete ) {
790*cdf0e10cSrcweir        print "REMOVE: $to\n" if $opt_verbose;
791*cdf0e10cSrcweir        $rc = unlink($to) unless $opt_check;
792*cdf0e10cSrcweir        return 1 if $opt_check;
793*cdf0e10cSrcweir        return $rc;
794*cdf0e10cSrcweir    }
795*cdf0e10cSrcweir
796*cdf0e10cSrcweir    if( !$opt_check && $opt_link ) {
797*cdf0e10cSrcweir        # hard link if possible
798*cdf0e10cSrcweir        if( link($from, $to) ){
799*cdf0e10cSrcweir            print "LINK: $from -> $to\n" if $opt_verbose;
800*cdf0e10cSrcweir            return 1;
801*cdf0e10cSrcweir        }
802*cdf0e10cSrcweir    }
803*cdf0e10cSrcweir
804*cdf0e10cSrcweir    if( $touch ) {
805*cdf0e10cSrcweir       print "TOUCH: $from -> $to\n" if $opt_verbose;
806*cdf0e10cSrcweir    }
807*cdf0e10cSrcweir    else {
808*cdf0e10cSrcweir       print "COPY: $from -> $to\n" if $opt_verbose;
809*cdf0e10cSrcweir    }
810*cdf0e10cSrcweir
811*cdf0e10cSrcweir    return 1 if( $opt_check );
812*cdf0e10cSrcweir
813*cdf0e10cSrcweir    #
814*cdf0e10cSrcweir    # copy to temporary file first and rename later
815*cdf0e10cSrcweir    # to minimize the possibility for race conditions
816*cdf0e10cSrcweir    local $temp_file = sprintf('%s.%d-%d', $to, $$, time());
817*cdf0e10cSrcweir    $rc = '';
818*cdf0e10cSrcweir    if (($strip ne '') && (defined $ENV{PROEXT}) && (is_unstripped($from))) {
819*cdf0e10cSrcweir        $rc = strip_target($from, $temp_file);
820*cdf0e10cSrcweir    } else {
821*cdf0e10cSrcweir        $rc = copy($from, $temp_file);
822*cdf0e10cSrcweir    };
823*cdf0e10cSrcweir    if ( $rc) {
824*cdf0e10cSrcweir        if ( is_newer($temp_file, $from, 0) ) {
825*cdf0e10cSrcweir            $rc = utime($$from_stat_ref[9], $$from_stat_ref[9], $temp_file);
826*cdf0e10cSrcweir            if ( !$rc ) {
827*cdf0e10cSrcweir                print_warning("can't update temporary file modification time '$temp_file': $!\n
828*cdf0e10cSrcweir                               Check file permissions of '$from'.",0);
829*cdf0e10cSrcweir            }
830*cdf0e10cSrcweir        }
831*cdf0e10cSrcweir        fix_file_permissions($$from_stat_ref[2], $temp_file);
832*cdf0e10cSrcweir        if ( $^O eq 'os2' )
833*cdf0e10cSrcweir        {
834*cdf0e10cSrcweir            $rc = unlink($to); # YD OS/2 can't rename if $to exists!
835*cdf0e10cSrcweir        }
836*cdf0e10cSrcweir        # Ugly hack: on windows file locking(?) sometimes prevents renaming.
837*cdf0e10cSrcweir        # Until we've found and fixed the real reason try it repeatedly :-(
838*cdf0e10cSrcweir        my $try = 0;
839*cdf0e10cSrcweir        my $maxtries = 1;
840*cdf0e10cSrcweir        $maxtries = 5 if ( $^O eq 'MSWin32' );
841*cdf0e10cSrcweir        my $success = 0;
842*cdf0e10cSrcweir        while ( $try < $maxtries && ! $success ) {
843*cdf0e10cSrcweir            sleep $try;
844*cdf0e10cSrcweir            $try ++;
845*cdf0e10cSrcweir            $success = rename($temp_file, $to);
846*cdf0e10cSrcweir            if ( $^O eq 'cygwin' && $to =~ /\.bin$/) {
847*cdf0e10cSrcweir                # hack to survive automatically added .exe for executables renamed to
848*cdf0e10cSrcweir                # *.bin - will break if there is intentionally a .bin _and_ .bin.exe file.
849*cdf0e10cSrcweir                $success = rename( "$to.exe", $to ) if -f "$to.exe";
850*cdf0e10cSrcweir            }
851*cdf0e10cSrcweir        }
852*cdf0e10cSrcweir        if ( $success ) {
853*cdf0e10cSrcweir            # handle special packaging of *.dylib files for Mac OS X
854*cdf0e10cSrcweir            if ( $^O eq 'darwin' )
855*cdf0e10cSrcweir            {
856*cdf0e10cSrcweir                system("macosx-create-bundle", "$to=$from.app") if ( -d "$from.app" );
857*cdf0e10cSrcweir                system("ranlib", "$to" ) if ( $to =~ /\.a/ );
858*cdf0e10cSrcweir            }
859*cdf0e10cSrcweir            if ( $try > 1 ) {
860*cdf0e10cSrcweir                print_warning("File '$to' temporarily locked. Dependency bug?");
861*cdf0e10cSrcweir            }
862*cdf0e10cSrcweir            return 1;
863*cdf0e10cSrcweir        }
864*cdf0e10cSrcweir        else {
865*cdf0e10cSrcweir            print_error("can't rename temporary file to $to: $!",0);
866*cdf0e10cSrcweir        }
867*cdf0e10cSrcweir    }
868*cdf0e10cSrcweir    else {
869*cdf0e10cSrcweir        print_error("can't copy $from: $!",0);
870*cdf0e10cSrcweir        my $destdir = dirname($to);
871*cdf0e10cSrcweir        if ( ! -d $destdir ) {
872*cdf0e10cSrcweir            print_error("directory '$destdir' does not exist", 0);
873*cdf0e10cSrcweir        }
874*cdf0e10cSrcweir    }
875*cdf0e10cSrcweir    unlink($temp_file);
876*cdf0e10cSrcweir    return 0;
877*cdf0e10cSrcweir}
878*cdf0e10cSrcweir
879*cdf0e10cSrcweirsub is_newer
880*cdf0e10cSrcweir{
881*cdf0e10cSrcweir        # returns whole stat buffer if newer
882*cdf0e10cSrcweir        my $from = shift;
883*cdf0e10cSrcweir        my $to = shift;
884*cdf0e10cSrcweir        my $touch = shift;
885*cdf0e10cSrcweir        my (@from_stat, @to_stat);
886*cdf0e10cSrcweir
887*cdf0e10cSrcweir        @from_stat = stat($from.$maybedot);
888*cdf0e10cSrcweir        if ( $opt_checkdlst ) {
889*cdf0e10cSrcweir            my $outtree = expand_macros("%__SRC%");
890*cdf0e10cSrcweir            my $commonouttree = expand_macros("%COMMON_OUTDIR%");
891*cdf0e10cSrcweir            if ( $from !~ /$outtree/ ) {
892*cdf0e10cSrcweir                if ( $from !~ /$commonouttree/ ) {
893*cdf0e10cSrcweir                    print_warning("'$from' does not exist") unless -e _;
894*cdf0e10cSrcweir                }
895*cdf0e10cSrcweir            }
896*cdf0e10cSrcweir        }
897*cdf0e10cSrcweir        return 0 unless -f _;
898*cdf0e10cSrcweir
899*cdf0e10cSrcweir        if ( $touch ) {
900*cdf0e10cSrcweir            $from_stat[9] = time();
901*cdf0e10cSrcweir        }
902*cdf0e10cSrcweir        # adjust timestamps to even seconds
903*cdf0e10cSrcweir        # this is necessary since NT platforms have a
904*cdf0e10cSrcweir        # 2s modified time granularity while the timestamps
905*cdf0e10cSrcweir        # on Samba volumes have a 1s granularity
906*cdf0e10cSrcweir
907*cdf0e10cSrcweir        $from_stat[9]-- if $from_stat[9] % 2;
908*cdf0e10cSrcweir
909*cdf0e10cSrcweir        if ( $to =~ /^\Q$dest\E/ ) {
910*cdf0e10cSrcweir            if ( $from_stat[9] > $logfiledate ) {
911*cdf0e10cSrcweir                $logfiledate = $from_stat[9];
912*cdf0e10cSrcweir            }
913*cdf0e10cSrcweir        } elsif ( $common_build && ( $to =~ /^\Q$common_dest\E/ ) ) {
914*cdf0e10cSrcweir            if ( $from_stat[9] > $commonlogfiledate ) {
915*cdf0e10cSrcweir                $commonlogfiledate = $from_stat[9];
916*cdf0e10cSrcweir            }
917*cdf0e10cSrcweir        }
918*cdf0e10cSrcweir
919*cdf0e10cSrcweir        @to_stat = stat($to.$maybedot);
920*cdf0e10cSrcweir        return \@from_stat unless -f _;
921*cdf0e10cSrcweir
922*cdf0e10cSrcweir        if ( $opt_force ) {
923*cdf0e10cSrcweir            return \@from_stat;
924*cdf0e10cSrcweir        }
925*cdf0e10cSrcweir        else {
926*cdf0e10cSrcweir            return ($from_stat[9] > $to_stat[9]) ? \@from_stat : 0;
927*cdf0e10cSrcweir        }
928*cdf0e10cSrcweir}
929*cdf0e10cSrcweir
930*cdf0e10cSrcweirsub filter_out
931*cdf0e10cSrcweir{
932*cdf0e10cSrcweir    my $file = shift;
933*cdf0e10cSrcweir
934*cdf0e10cSrcweir    foreach my $pattern ( @copy_filter_patterns ) {
935*cdf0e10cSrcweir        if  ( $file =~ /$pattern/ ) {
936*cdf0e10cSrcweir           print "filter out: $file\n" if $is_debug;
937*cdf0e10cSrcweir           return 1;
938*cdf0e10cSrcweir        }
939*cdf0e10cSrcweir    }
940*cdf0e10cSrcweir
941*cdf0e10cSrcweir    return 0;
942*cdf0e10cSrcweir}
943*cdf0e10cSrcweir
944*cdf0e10cSrcweirsub fix_file_permissions
945*cdf0e10cSrcweir{
946*cdf0e10cSrcweir    my $mode = shift;
947*cdf0e10cSrcweir    my $file = shift;
948*cdf0e10cSrcweir
949*cdf0e10cSrcweir    if ( ($mode >> 6) % 2 == 1 ) {
950*cdf0e10cSrcweir        $mode = 0777 & ~$umask;
951*cdf0e10cSrcweir    }
952*cdf0e10cSrcweir    else {
953*cdf0e10cSrcweir        $mode = 0666 & ~$umask;
954*cdf0e10cSrcweir    }
955*cdf0e10cSrcweir    chmod($mode, $file);
956*cdf0e10cSrcweir}
957*cdf0e10cSrcweir
958*cdf0e10cSrcweirsub get_latest_patchlevel
959*cdf0e10cSrcweir{
960*cdf0e10cSrcweir    # note: feed only well formed library names to this function
961*cdf0e10cSrcweir    # of the form libfoo.so.x.y.z with x,y,z numbers
962*cdf0e10cSrcweir
963*cdf0e10cSrcweir    my @sorted_files = sort by_rev @_;
964*cdf0e10cSrcweir    return $sorted_files[-1];
965*cdf0e10cSrcweir
966*cdf0e10cSrcweir    sub by_rev {
967*cdf0e10cSrcweir    # comparison function for sorting
968*cdf0e10cSrcweir        my (@field_a, @field_b, $i);
969*cdf0e10cSrcweir
970*cdf0e10cSrcweir        $a =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)\.(\d+)\.(\d+)$/;
971*cdf0e10cSrcweir        @field_a = ($3, $4, $5);
972*cdf0e10cSrcweir        $b =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)\.(\d+)\.(\d+)$/;
973*cdf0e10cSrcweir        @field_b = ($3, $4, $5);
974*cdf0e10cSrcweir
975*cdf0e10cSrcweir        for ($i = 0; $i < 3; $i++)
976*cdf0e10cSrcweir          {
977*cdf0e10cSrcweir              if ( ($field_a[$i] < $field_b[$i]) ) {
978*cdf0e10cSrcweir                  return -1;
979*cdf0e10cSrcweir              }
980*cdf0e10cSrcweir              if ( ($field_a[$i] > $field_b[$i]) ) {
981*cdf0e10cSrcweir                  return 1;
982*cdf0e10cSrcweir              }
983*cdf0e10cSrcweir          }
984*cdf0e10cSrcweir
985*cdf0e10cSrcweir        # can't happen
986*cdf0e10cSrcweir        return 0;
987*cdf0e10cSrcweir    }
988*cdf0e10cSrcweir
989*cdf0e10cSrcweir}
990*cdf0e10cSrcweir
991*cdf0e10cSrcweirsub push_default_actions
992*cdf0e10cSrcweir{
993*cdf0e10cSrcweir    # any default action (that is an action which must be done even without
994*cdf0e10cSrcweir    # a corresponding d.lst entry) should be pushed here on the
995*cdf0e10cSrcweir    # @action_data list.
996*cdf0e10cSrcweir    my $subdir;
997*cdf0e10cSrcweir    my @subdirs = (
998*cdf0e10cSrcweir                    'bin',
999*cdf0e10cSrcweir                    'doc',
1000*cdf0e10cSrcweir                    'inc',
1001*cdf0e10cSrcweir                    'lib',
1002*cdf0e10cSrcweir                    'par',
1003*cdf0e10cSrcweir                    'pck',
1004*cdf0e10cSrcweir                    'rdb',
1005*cdf0e10cSrcweir                    'res',
1006*cdf0e10cSrcweir                    'xml'
1007*cdf0e10cSrcweir                );
1008*cdf0e10cSrcweir    push(@subdirs, 'zip') if $opt_zip;
1009*cdf0e10cSrcweir    push(@subdirs, 'idl') if ! $common_build;
1010*cdf0e10cSrcweir    push(@subdirs, 'pus') if ! $common_build;
1011*cdf0e10cSrcweir    my @common_subdirs = (
1012*cdf0e10cSrcweir                    'bin',
1013*cdf0e10cSrcweir                    'idl',
1014*cdf0e10cSrcweir                    'inc',
1015*cdf0e10cSrcweir                    'pck',
1016*cdf0e10cSrcweir                    'pus',
1017*cdf0e10cSrcweir                    'res'
1018*cdf0e10cSrcweir                );
1019*cdf0e10cSrcweir    push(@common_subdirs, 'zip') if $opt_zip;
1020*cdf0e10cSrcweir
1021*cdf0e10cSrcweir    if ( ! $opt_delete ) {
1022*cdf0e10cSrcweir        # create all the subdirectories on solver
1023*cdf0e10cSrcweir        foreach $subdir (@subdirs) {
1024*cdf0e10cSrcweir            push(@action_data, ['mkdir', "%_DEST%/$subdir%_EXT%"]);
1025*cdf0e10cSrcweir        }
1026*cdf0e10cSrcweir        if ( $common_build ) {
1027*cdf0e10cSrcweir            foreach $subdir (@common_subdirs) {
1028*cdf0e10cSrcweir                push(@action_data, ['mkdir', "%COMMON_DEST%/$subdir%_EXT%"]);
1029*cdf0e10cSrcweir            }
1030*cdf0e10cSrcweir        }
1031*cdf0e10cSrcweir    }
1032*cdf0e10cSrcweir    push(@action_data, ['mkdir', "%_DEST%/inc%_EXT%/$module"]);
1033*cdf0e10cSrcweir    if ( $common_build ) {
1034*cdf0e10cSrcweir        push(@action_data, ['mkdir', "%COMMON_DEST%/inc%_EXT%/$module"]);
1035*cdf0e10cSrcweir        push(@action_data, ['mkdir', "%COMMON_DEST%/res%_EXT%/img"]);
1036*cdf0e10cSrcweir    } else {
1037*cdf0e10cSrcweir        push(@action_data, ['mkdir', "%_DEST%/res%_EXT%/img"]);
1038*cdf0e10cSrcweir    }
1039*cdf0e10cSrcweir
1040*cdf0e10cSrcweir    # deliver build.lst to $dest/inc/$module
1041*cdf0e10cSrcweir    push(@action_data, ['copy', "build.lst %_DEST%/inc%_EXT%/$module/build.lst"]);
1042*cdf0e10cSrcweir    if ( $common_build ) {
1043*cdf0e10cSrcweir        # ... and to $common_dest/inc/$module
1044*cdf0e10cSrcweir        push(@action_data, ['copy', "build.lst %COMMON_DEST%/inc%_EXT%/$module/build.lst"]);
1045*cdf0e10cSrcweir    }
1046*cdf0e10cSrcweir
1047*cdf0e10cSrcweir    # need to copy libstaticmxp.dylib for Mac OS X
1048*cdf0e10cSrcweir    if ( $^O eq 'darwin' )
1049*cdf0e10cSrcweir    {
1050*cdf0e10cSrcweir        push(@action_data, ['copy', "../%__SRC%/lib/lib*static*.dylib %_DEST%/lib%_EXT%/lib*static*.dylib"]);
1051*cdf0e10cSrcweir    }
1052*cdf0e10cSrcweir}
1053*cdf0e10cSrcweir
1054*cdf0e10cSrcweirsub walk_addincpath_list
1055*cdf0e10cSrcweir{
1056*cdf0e10cSrcweir    my (@addincpath_headers);
1057*cdf0e10cSrcweir    return if $#addincpath_list == -1;
1058*cdf0e10cSrcweir
1059*cdf0e10cSrcweir    # create hash with all addincpath header names
1060*cdf0e10cSrcweir    for (my $i = 0; $i <= $#addincpath_list; $i++) {
1061*cdf0e10cSrcweir        my @field = split('/', $addincpath_list[$i][0]);
1062*cdf0e10cSrcweir        push (@addincpath_headers, $field[-1]);
1063*cdf0e10cSrcweir    }
1064*cdf0e10cSrcweir
1065*cdf0e10cSrcweir    # now stream all addincpath headers through addincpath filter
1066*cdf0e10cSrcweir    for (my $i = 0; $i <= $#addincpath_list; $i++) {
1067*cdf0e10cSrcweir        add_incpath_if_newer($addincpath_list[$i][0], $addincpath_list[$i][1], \@addincpath_headers)
1068*cdf0e10cSrcweir                ? $files_copied++ : $files_unchanged++;
1069*cdf0e10cSrcweir    }
1070*cdf0e10cSrcweir}
1071*cdf0e10cSrcweir
1072*cdf0e10cSrcweirsub add_incpath_if_newer
1073*cdf0e10cSrcweir{
1074*cdf0e10cSrcweir    my $from = shift;
1075*cdf0e10cSrcweir    my $to = shift;
1076*cdf0e10cSrcweir    my $modify_headers_ref = shift;
1077*cdf0e10cSrcweir    my ($from_stat_ref, $header);
1078*cdf0e10cSrcweir
1079*cdf0e10cSrcweir    push_on_ziplist($to) if $opt_zip;
1080*cdf0e10cSrcweir    push_on_loglist("ADDINCPATH", "$from", "$to") if $opt_log;
1081*cdf0e10cSrcweir
1082*cdf0e10cSrcweir    if ( $opt_delete ) {
1083*cdf0e10cSrcweir        print "REMOVE: $to\n" if $opt_verbose;
1084*cdf0e10cSrcweir        my $rc = unlink($to);
1085*cdf0e10cSrcweir        return 1 if $rc;
1086*cdf0e10cSrcweir        return 0;
1087*cdf0e10cSrcweir    }
1088*cdf0e10cSrcweir
1089*cdf0e10cSrcweir    if ( $from_stat_ref = is_newer($from, $to) ) {
1090*cdf0e10cSrcweir        print "ADDINCPATH: $from -> $to\n" if $opt_verbose;
1091*cdf0e10cSrcweir
1092*cdf0e10cSrcweir        return 1 if $opt_check;
1093*cdf0e10cSrcweir
1094*cdf0e10cSrcweir        my $save = $/;
1095*cdf0e10cSrcweir        undef $/;
1096*cdf0e10cSrcweir        open(FROM, "<$from");
1097*cdf0e10cSrcweir        # slurp whole file in one big string
1098*cdf0e10cSrcweir        my $content = <FROM>;
1099*cdf0e10cSrcweir        close(FROM);
1100*cdf0e10cSrcweir        $/ = $save;
1101*cdf0e10cSrcweir
1102*cdf0e10cSrcweir        foreach $header (@$modify_headers_ref) {
1103*cdf0e10cSrcweir            $content =~ s/#include [<"]$header[>"]/#include <$module\/$header>/g;
1104*cdf0e10cSrcweir        }
1105*cdf0e10cSrcweir
1106*cdf0e10cSrcweir        open(TO, ">$to");
1107*cdf0e10cSrcweir        print TO $content;
1108*cdf0e10cSrcweir        close(TO);
1109*cdf0e10cSrcweir
1110*cdf0e10cSrcweir        utime($$from_stat_ref[9], $$from_stat_ref[9], $to);
1111*cdf0e10cSrcweir        fix_file_permissions($$from_stat_ref[2], $to);
1112*cdf0e10cSrcweir        return 1;
1113*cdf0e10cSrcweir    }
1114*cdf0e10cSrcweir    return 0;
1115*cdf0e10cSrcweir}
1116*cdf0e10cSrcweir
1117*cdf0e10cSrcweirsub push_on_ziplist
1118*cdf0e10cSrcweir{
1119*cdf0e10cSrcweir    my $file = shift;
1120*cdf0e10cSrcweir    return if ( $opt_check );
1121*cdf0e10cSrcweir    # strip $dest from path since we don't want to record it in zip file
1122*cdf0e10cSrcweir    if ( $file =~ s#^\Q$dest\E/##o ) {
1123*cdf0e10cSrcweir        if ( $updminor ){
1124*cdf0e10cSrcweir            # strip minor from path
1125*cdf0e10cSrcweir            my $ext = "%_EXT%";
1126*cdf0e10cSrcweir            $ext = expand_macros($ext);
1127*cdf0e10cSrcweir            $file =~ s#^$ext##o;
1128*cdf0e10cSrcweir        }
1129*cdf0e10cSrcweir        push(@zip_list, $file);
1130*cdf0e10cSrcweir    } elsif ( $file =~ s#^\Q$common_dest\E/##o ) {
1131*cdf0e10cSrcweir        if ( $updminor ){
1132*cdf0e10cSrcweir            # strip minor from path
1133*cdf0e10cSrcweir            my $ext = "%_EXT%";
1134*cdf0e10cSrcweir            $ext = expand_macros($ext);
1135*cdf0e10cSrcweir            $file =~ s#^$ext##o;
1136*cdf0e10cSrcweir        }
1137*cdf0e10cSrcweir        push(@common_zip_list, $file);
1138*cdf0e10cSrcweir    }
1139*cdf0e10cSrcweir}
1140*cdf0e10cSrcweir
1141*cdf0e10cSrcweirsub push_on_loglist
1142*cdf0e10cSrcweir{
1143*cdf0e10cSrcweir    my @entry = @_;
1144*cdf0e10cSrcweir    return 0 if ( $opt_check );
1145*cdf0e10cSrcweir    return -1 if ( $#entry != 2 );
1146*cdf0e10cSrcweir    if (( $entry[0] eq "COPY" ) || ( $entry[0] eq "ADDINCPATH" )) {
1147*cdf0e10cSrcweir        return 0 if ( ! -e $entry[1].$maybedot );
1148*cdf0e10cSrcweir        # make 'from' relative to source root
1149*cdf0e10cSrcweir        $entry[1] = $repository ."/" . $module . "/prj/" . $entry[1];
1150*cdf0e10cSrcweir        $entry[1] =~ s/$module\/prj\/\.\./$module/;
1151*cdf0e10cSrcweir    }
1152*cdf0e10cSrcweir    # platform or common tree?
1153*cdf0e10cSrcweir    my $common;
1154*cdf0e10cSrcweir    if ( $entry[2] =~ /^\Q$dest\E/ ) {
1155*cdf0e10cSrcweir        $common = 0;
1156*cdf0e10cSrcweir    } elsif ( $common_build && ( $entry[2] =~ /^\Q$common_dest\E/ )) {
1157*cdf0e10cSrcweir        $common = 1;
1158*cdf0e10cSrcweir    } else {
1159*cdf0e10cSrcweir        warn "Neither common nor platform tree?";
1160*cdf0e10cSrcweir        return;
1161*cdf0e10cSrcweir    }
1162*cdf0e10cSrcweir    # make 'to' relative to SOLARVERSION
1163*cdf0e10cSrcweir    my $solarversion  = $ENV{'SOLARVERSION'};
1164*cdf0e10cSrcweir    $solarversion =~ s#\\#/#g;
1165*cdf0e10cSrcweir    $entry[2] =~ s/^\Q$solarversion\E\///;
1166*cdf0e10cSrcweir    # strip minor from 'to'
1167*cdf0e10cSrcweir    my $ext = "%_EXT%";
1168*cdf0e10cSrcweir    $ext = expand_macros($ext);
1169*cdf0e10cSrcweir    $entry[2] =~ s#$ext([\\\/])#$1#o;
1170*cdf0e10cSrcweir
1171*cdf0e10cSrcweir    if ( $common ) {
1172*cdf0e10cSrcweir        push @common_log_list, [@entry];
1173*cdf0e10cSrcweir    } else {
1174*cdf0e10cSrcweir        push @log_list, [@entry];
1175*cdf0e10cSrcweir    }
1176*cdf0e10cSrcweir    return 1;
1177*cdf0e10cSrcweir}
1178*cdf0e10cSrcweir
1179*cdf0e10cSrcweirsub zip_files
1180*cdf0e10cSrcweir{
1181*cdf0e10cSrcweir    my $zipexe = 'zip';
1182*cdf0e10cSrcweir    $zipexe .= ' -y' unless  $^O eq 'MSWin32';
1183*cdf0e10cSrcweir
1184*cdf0e10cSrcweir    my ($platform_zip_file, $common_zip_file);
1185*cdf0e10cSrcweir    $platform_zip_file = "%_DEST%/zip%_EXT%/$module.zip";
1186*cdf0e10cSrcweir    $platform_zip_file = expand_macros($platform_zip_file);
1187*cdf0e10cSrcweir    my (%dest_dir, %list_ref);
1188*cdf0e10cSrcweir    $dest_dir{$platform_zip_file} = $dest;
1189*cdf0e10cSrcweir    $list_ref{$platform_zip_file} = \@zip_list;
1190*cdf0e10cSrcweir    if ( $common_build ) {
1191*cdf0e10cSrcweir        $common_zip_file = "%COMMON_DEST%/zip%_EXT%/$module.zip";
1192*cdf0e10cSrcweir        $common_zip_file = expand_macros($common_zip_file);
1193*cdf0e10cSrcweir        $dest_dir{$common_zip_file}   = $common_dest;
1194*cdf0e10cSrcweir        $list_ref{$common_zip_file}   = \@common_zip_list;
1195*cdf0e10cSrcweir    }
1196*cdf0e10cSrcweir
1197*cdf0e10cSrcweir    my $ext = "%_EXT%";
1198*cdf0e10cSrcweir    $ext = expand_macros($ext);
1199*cdf0e10cSrcweir
1200*cdf0e10cSrcweir    my @zipfiles;
1201*cdf0e10cSrcweir    $zipfiles[0] = $platform_zip_file;
1202*cdf0e10cSrcweir    if ( $common_build ) {
1203*cdf0e10cSrcweir        push @zipfiles, ($common_zip_file);
1204*cdf0e10cSrcweir    }
1205*cdf0e10cSrcweir    foreach my $zip_file ( @zipfiles ) {
1206*cdf0e10cSrcweir        print "ZIP: updating $zip_file\n" if $opt_verbose;
1207*cdf0e10cSrcweir        next if ( $opt_check );
1208*cdf0e10cSrcweir
1209*cdf0e10cSrcweir        if ( $opt_delete ) {
1210*cdf0e10cSrcweir            if ( -e $zip_file ) {
1211*cdf0e10cSrcweir                unlink $zip_file or die "Error: can't remove file '$zip_file': $!";
1212*cdf0e10cSrcweir            }
1213*cdf0e10cSrcweir            next;
1214*cdf0e10cSrcweir        }
1215*cdf0e10cSrcweir
1216*cdf0e10cSrcweir        local $work_file = "";
1217*cdf0e10cSrcweir        if ( $zip_file eq $common_zip_file) {
1218*cdf0e10cSrcweir            # Zip file in common tree: work on uniq copy to avoid collisions
1219*cdf0e10cSrcweir            $work_file = $zip_file;
1220*cdf0e10cSrcweir            $work_file =~ s/\.zip$//;
1221*cdf0e10cSrcweir            $work_file .= (sprintf('.%d-%d', $$, time())) . ".zip";
1222*cdf0e10cSrcweir            die "Error: temp file $work_file already exists" if ( -e $work_file);
1223*cdf0e10cSrcweir            if ( -e $zip_file ) {
1224*cdf0e10cSrcweir                if ( -z $zip_file) {
1225*cdf0e10cSrcweir                    # sometimes there are files of 0 byte size - remove them
1226*cdf0e10cSrcweir                    unlink $zip_file or print_error("can't remove empty file '$zip_file': $!",0);
1227*cdf0e10cSrcweir                } else {
1228*cdf0e10cSrcweir                    if ( ! copy($zip_file, $work_file)) {
1229*cdf0e10cSrcweir                        # give a warning, not an error:
1230*cdf0e10cSrcweir                        # we can zip from scratch instead of just updating the old zip file
1231*cdf0e10cSrcweir                        print_warning("can't copy'$zip_file' into '$work_file': $!", 0);
1232*cdf0e10cSrcweir                        unlink $work_file;
1233*cdf0e10cSrcweir                    }
1234*cdf0e10cSrcweir                }
1235*cdf0e10cSrcweir            }
1236*cdf0e10cSrcweir        } else {
1237*cdf0e10cSrcweir            # No pre processing necessary, working directly on solver.
1238*cdf0e10cSrcweir            $work_file = $zip_file;
1239*cdf0e10cSrcweir        }
1240*cdf0e10cSrcweir
1241*cdf0e10cSrcweir        # zip content has to be relative to $dest_dir
1242*cdf0e10cSrcweir        chdir($dest_dir{$zip_file}) or die "Error: cannot chdir into $dest_dir{$zip_file}";
1243*cdf0e10cSrcweir        my $this_ref = $list_ref{$zip_file};
1244*cdf0e10cSrcweir        open(ZIP, "| $zipexe -q -o -u -@ $work_file") or die "error opening zip file";
1245*cdf0e10cSrcweir        foreach $file ( @$this_ref ) {
1246*cdf0e10cSrcweir            print "ZIP: adding $file to $zip_file\n" if $is_debug;
1247*cdf0e10cSrcweir            print ZIP "$file\n";
1248*cdf0e10cSrcweir        }
1249*cdf0e10cSrcweir        close(ZIP);
1250*cdf0e10cSrcweir        fix_broken_cygwin_created_zips($work_file) if $^O eq "cygwin";
1251*cdf0e10cSrcweir
1252*cdf0e10cSrcweir        if ( $zip_file eq $common_zip_file) {
1253*cdf0e10cSrcweir            # rename work file back
1254*cdf0e10cSrcweir            if ( -e $work_file ) {
1255*cdf0e10cSrcweir                if ( -e $zip_file) {
1256*cdf0e10cSrcweir                    # do some tricks to be fast. otherwise we may disturb other platforms
1257*cdf0e10cSrcweir                    # by unlinking a file which just gets copied -> stale file handle.
1258*cdf0e10cSrcweir                    my $buffer_file=$work_file . '_rm';
1259*cdf0e10cSrcweir                    rename($zip_file, $buffer_file) or warn "Warning: can't rename old zip file '$zip_file': $!";
1260*cdf0e10cSrcweir                    if (! rename($work_file, $zip_file)) {
1261*cdf0e10cSrcweir                        print_error("can't rename temporary file to $zip_file: $!",0);
1262*cdf0e10cSrcweir                        unlink $work_file;
1263*cdf0e10cSrcweir                    }
1264*cdf0e10cSrcweir                    unlink $buffer_file;
1265*cdf0e10cSrcweir                } else {
1266*cdf0e10cSrcweir                    if (! rename($work_file, $zip_file)) {
1267*cdf0e10cSrcweir                        print_error("can't rename temporary file to $zip_file: $!",0);
1268*cdf0e10cSrcweir                        unlink $work_file;
1269*cdf0e10cSrcweir                    }
1270*cdf0e10cSrcweir                }
1271*cdf0e10cSrcweir            }
1272*cdf0e10cSrcweir        }
1273*cdf0e10cSrcweir    }
1274*cdf0e10cSrcweir}
1275*cdf0e10cSrcweir
1276*cdf0e10cSrcweirsub fix_broken_cygwin_created_zips
1277*cdf0e10cSrcweir# add given extension to or strip it from stored path
1278*cdf0e10cSrcweir{
1279*cdf0e10cSrcweir    require Archive::Zip; import Archive::Zip;
1280*cdf0e10cSrcweir    my $zip_file = shift;
1281*cdf0e10cSrcweir
1282*cdf0e10cSrcweir    $zip = Archive::Zip->new();
1283*cdf0e10cSrcweir    unless ( $zip->read($work_file) == AZ_OK ) {
1284*cdf0e10cSrcweir        die "Error: can't open zip file '$zip_file' to fix broken cygwin file permissions";
1285*cdf0e10cSrcweir    }
1286*cdf0e10cSrcweir    my $latest_member_mod_time = 0;
1287*cdf0e10cSrcweir    foreach $member ( $zip->members() ) {
1288*cdf0e10cSrcweir        my $attributes = $member->unixFileAttributes();
1289*cdf0e10cSrcweir        $attributes &= ~0xFE00;
1290*cdf0e10cSrcweir        print $member->fileName() . ": " . sprintf("%lo", $attributes) if $is_debug;
1291*cdf0e10cSrcweir        $attributes |= 0x10; # add group write permission
1292*cdf0e10cSrcweir        print "-> " . sprintf("%lo", $attributes) . "\n" if $is_debug;
1293*cdf0e10cSrcweir        $member->unixFileAttributes($attributes);
1294*cdf0e10cSrcweir        if ( $latest_member_mod_time < $member->lastModTime() ) {
1295*cdf0e10cSrcweir            $latest_member_mod_time = $member->lastModTime();
1296*cdf0e10cSrcweir        }
1297*cdf0e10cSrcweir    }
1298*cdf0e10cSrcweir    die "Error: can't overwrite zip file '$zip_file' for fixing permissions" unless $zip->overwrite() == AZ_OK;
1299*cdf0e10cSrcweir    utime($latest_member_mod_time, $latest_member_mod_time, $zip_file);
1300*cdf0e10cSrcweir}
1301*cdf0e10cSrcweir
1302*cdf0e10cSrcweirsub get_tempfilename
1303*cdf0e10cSrcweir{
1304*cdf0e10cSrcweir    my $temp_dir = shift;
1305*cdf0e10cSrcweir    $temp_dir = ( -d '/tmp' ? '/tmp' : $ENV{TMPDIR} || $ENV{TEMP} || '.' )
1306*cdf0e10cSrcweir            unless defined($temp_dir);
1307*cdf0e10cSrcweir 	if ( ! -d $temp_dir ) {
1308*cdf0e10cSrcweir        die "no temp directory $temp_dir\n";
1309*cdf0e10cSrcweir    }
1310*cdf0e10cSrcweir    my $base_name = sprintf( "%d-%di-%d", $$, time(), $tempcounter++ );
1311*cdf0e10cSrcweir    return "$temp_dir/$base_name";
1312*cdf0e10cSrcweir}
1313*cdf0e10cSrcweir
1314*cdf0e10cSrcweirsub write_log
1315*cdf0e10cSrcweir{
1316*cdf0e10cSrcweir    my (%log_file, %file_date);
1317*cdf0e10cSrcweir    $log_file{\@log_list} = "%_DEST%/inc%_EXT%/$module/deliver.log";
1318*cdf0e10cSrcweir    $log_file{\@common_log_list} = "%COMMON_DEST%/inc%_EXT%/$module/deliver.log";
1319*cdf0e10cSrcweir    $file_date{\@log_list} = $logfiledate;
1320*cdf0e10cSrcweir    $file_date{\@common_log_list} = $commonlogfiledate;
1321*cdf0e10cSrcweir
1322*cdf0e10cSrcweir    my @logs = ( \@log_list );
1323*cdf0e10cSrcweir    push @logs, ( \@common_log_list ) if ( $common_build );
1324*cdf0e10cSrcweir    foreach my $log ( @logs ) {
1325*cdf0e10cSrcweir        $log_file{$log} = expand_macros( $log_file{$log} );
1326*cdf0e10cSrcweir        if ( $opt_delete ) {
1327*cdf0e10cSrcweir            print "LOG: removing $log_file{$log}\n" if $opt_verbose;
1328*cdf0e10cSrcweir            next if ( $opt_check );
1329*cdf0e10cSrcweir            unlink $log_file{$log};
1330*cdf0e10cSrcweir        } else {
1331*cdf0e10cSrcweir            print "LOG: writing $log_file{$log}\n" if $opt_verbose;
1332*cdf0e10cSrcweir            next if ( $opt_check );
1333*cdf0e10cSrcweir            open( LOGFILE, "> $log_file{$log}" ) or warn "Error: could not open log file.";
1334*cdf0e10cSrcweir            foreach my $item ( @$log ) {
1335*cdf0e10cSrcweir                print LOGFILE "@$item\n";
1336*cdf0e10cSrcweir            }
1337*cdf0e10cSrcweir            close( LOGFILE );
1338*cdf0e10cSrcweir            utime($file_date{$log}, $file_date{$log}, $log_file{$log});
1339*cdf0e10cSrcweir        }
1340*cdf0e10cSrcweir        push_on_ziplist( $log_file{$log} ) if $opt_zip;
1341*cdf0e10cSrcweir    }
1342*cdf0e10cSrcweir    return;
1343*cdf0e10cSrcweir}
1344*cdf0e10cSrcweir
1345*cdf0e10cSrcweirsub check_dlst
1346*cdf0e10cSrcweir{
1347*cdf0e10cSrcweir    my %createddir;
1348*cdf0e10cSrcweir    my %destdir;
1349*cdf0e10cSrcweir    my %destfile;
1350*cdf0e10cSrcweir    # get all checkable actions to perform
1351*cdf0e10cSrcweir    foreach my $action ( @action_data ) {
1352*cdf0e10cSrcweir        my $path = expand_macros( $$action[1] );
1353*cdf0e10cSrcweir        if ( $$action[0] eq 'mkdir' ) {
1354*cdf0e10cSrcweir            $createddir{$path} ++;
1355*cdf0e10cSrcweir        } elsif (( $$action[0] eq 'copy' ) || ( $$action[0] eq 'addincpath' )) {
1356*cdf0e10cSrcweir            my ($from, $to) = split(' ', $path);
1357*cdf0e10cSrcweir            my ($to_fname, $to_dir);
1358*cdf0e10cSrcweir            my $withwildcard = 0;
1359*cdf0e10cSrcweir            if ( $from =~ /[\*\?\[\]]/ ) {
1360*cdf0e10cSrcweir                $withwildcard = 1;
1361*cdf0e10cSrcweir            }
1362*cdf0e10cSrcweir            ($to_fname, $to_dir) = fileparse($to);
1363*cdf0e10cSrcweir            if ( $withwildcard ) {
1364*cdf0e10cSrcweir                if ( $to !~ /[\*\?\[\]]/ ) {
1365*cdf0e10cSrcweir                    $to_dir = $to;
1366*cdf0e10cSrcweir                    $to_fname ='';
1367*cdf0e10cSrcweir                }
1368*cdf0e10cSrcweir            }
1369*cdf0e10cSrcweir            $to_dir =~ s/[\\\/\s]$//;
1370*cdf0e10cSrcweir            $destdir{$to_dir} ++;
1371*cdf0e10cSrcweir            # Check: copy into non existing directory?
1372*cdf0e10cSrcweir            if ( ! $createddir{$to_dir} ) {
1373*cdf0e10cSrcweir                # unfortunately it is not so easy: it's OK if a subdirectory of $to_dir
1374*cdf0e10cSrcweir                # gets created, because mkpath creates the whole tree
1375*cdf0e10cSrcweir                foreach my $directory ( keys %createddir ) {
1376*cdf0e10cSrcweir                    if ( $directory =~ /^\Q$to_dir\E[\\\/]/ ) {
1377*cdf0e10cSrcweir                        $createddir{$to_dir} ++;
1378*cdf0e10cSrcweir                        last;
1379*cdf0e10cSrcweir                    }
1380*cdf0e10cSrcweir                }
1381*cdf0e10cSrcweir                print_warning("Possibly copying into directory without creating in before: '$to_dir'")
1382*cdf0e10cSrcweir                    unless $createddir{$to_dir};
1383*cdf0e10cSrcweir            }
1384*cdf0e10cSrcweir            # Check: overwrite file?
1385*cdf0e10cSrcweir            if ( ! $to ) {
1386*cdf0e10cSrcweir                if ( $destfile{$to} ) {
1387*cdf0e10cSrcweir                    print_warning("Multiple entries copying to '$to'");
1388*cdf0e10cSrcweir                }
1389*cdf0e10cSrcweir                $destfile{$to} ++;
1390*cdf0e10cSrcweir            }
1391*cdf0e10cSrcweir        }
1392*cdf0e10cSrcweir    }
1393*cdf0e10cSrcweir}
1394*cdf0e10cSrcweir
1395*cdf0e10cSrcweirsub cleanup
1396*cdf0e10cSrcweir{
1397*cdf0e10cSrcweir    # remove empty directories
1398*cdf0e10cSrcweir    foreach my $path ( @dirlist ) {
1399*cdf0e10cSrcweir        $path = expand_macros($path);
1400*cdf0e10cSrcweir        if ( $opt_check ) {
1401*cdf0e10cSrcweir            print "RMDIR: $path\n" if $opt_verbose;
1402*cdf0e10cSrcweir        } else {
1403*cdf0e10cSrcweir            rmdir $path;
1404*cdf0e10cSrcweir        }
1405*cdf0e10cSrcweir    }
1406*cdf0e10cSrcweir}
1407*cdf0e10cSrcweir
1408*cdf0e10cSrcweirsub delete_output
1409*cdf0e10cSrcweir{
1410*cdf0e10cSrcweir    my $output_path = expand_macros("../%__SRC%");
1411*cdf0e10cSrcweir    if ( "$output_path" ne "../" ) {
1412*cdf0e10cSrcweir        if ( rmtree([$output_path], 0, 1) ) {
1413*cdf0e10cSrcweir            print "Deleted output tree.\n" if $opt_verbose;
1414*cdf0e10cSrcweir        }
1415*cdf0e10cSrcweir        else {
1416*cdf0e10cSrcweir            print_error("Error deleting output tree $output_path: $!",0);
1417*cdf0e10cSrcweir        }
1418*cdf0e10cSrcweir    }
1419*cdf0e10cSrcweir    else {
1420*cdf0e10cSrcweir        print_error("Output not deleted - INPATH is not set");
1421*cdf0e10cSrcweir    }
1422*cdf0e10cSrcweir}
1423*cdf0e10cSrcweir
1424*cdf0e10cSrcweirsub print_warning
1425*cdf0e10cSrcweir{
1426*cdf0e10cSrcweir    my $message = shift;
1427*cdf0e10cSrcweir    my $line = shift;
1428*cdf0e10cSrcweir
1429*cdf0e10cSrcweir    print STDERR "$script_name: ";
1430*cdf0e10cSrcweir    if ( $dlst_file ) {
1431*cdf0e10cSrcweir        print STDERR "$dlst_file: ";
1432*cdf0e10cSrcweir    }
1433*cdf0e10cSrcweir    if ( $line ) {
1434*cdf0e10cSrcweir        print STDERR "line $line: ";
1435*cdf0e10cSrcweir    }
1436*cdf0e10cSrcweir    print STDERR "WARNING: $message\n";
1437*cdf0e10cSrcweir}
1438*cdf0e10cSrcweir
1439*cdf0e10cSrcweirsub print_error
1440*cdf0e10cSrcweir{
1441*cdf0e10cSrcweir    my $message = shift;
1442*cdf0e10cSrcweir    my $line = shift;
1443*cdf0e10cSrcweir
1444*cdf0e10cSrcweir    print STDERR "$script_name: ";
1445*cdf0e10cSrcweir    if ( $dlst_file ) {
1446*cdf0e10cSrcweir        print STDERR "$dlst_file: ";
1447*cdf0e10cSrcweir    }
1448*cdf0e10cSrcweir    if ( $line ) {
1449*cdf0e10cSrcweir        print STDERR "line $line: ";
1450*cdf0e10cSrcweir    }
1451*cdf0e10cSrcweir    print STDERR "ERROR: $message\n";
1452*cdf0e10cSrcweir    $error ++;
1453*cdf0e10cSrcweir}
1454*cdf0e10cSrcweir
1455*cdf0e10cSrcweirsub print_stats
1456*cdf0e10cSrcweir{
1457*cdf0e10cSrcweir    print "Module '$module' delivered ";
1458*cdf0e10cSrcweir    if ( $error ) {
1459*cdf0e10cSrcweir        print "with errors\n";
1460*cdf0e10cSrcweir    } else {
1461*cdf0e10cSrcweir        print "successfully.";
1462*cdf0e10cSrcweir        if ( $opt_delete ) {
1463*cdf0e10cSrcweir            print " $files_copied files removed,";
1464*cdf0e10cSrcweir        }
1465*cdf0e10cSrcweir        else {
1466*cdf0e10cSrcweir            print " $files_copied files copied,";
1467*cdf0e10cSrcweir        }
1468*cdf0e10cSrcweir        print " $files_unchanged files unchanged\n";
1469*cdf0e10cSrcweir    }
1470*cdf0e10cSrcweir}
1471*cdf0e10cSrcweir
1472*cdf0e10cSrcweirsub cleanup_and_die
1473*cdf0e10cSrcweir{
1474*cdf0e10cSrcweir    # clean up on unexpected termination
1475*cdf0e10cSrcweir    my $sig = shift;
1476*cdf0e10cSrcweir    if ( defined($temp_file) && -e $temp_file ) {
1477*cdf0e10cSrcweir        unlink($temp_file);
1478*cdf0e10cSrcweir    }
1479*cdf0e10cSrcweir    if ( defined($work_file) && -e $work_file ) {
1480*cdf0e10cSrcweir        unlink($work_file);
1481*cdf0e10cSrcweir        print STDERR "$work_file removed\n";
1482*cdf0e10cSrcweir    }
1483*cdf0e10cSrcweir
1484*cdf0e10cSrcweir    die "caught unexpected signal $sig, terminating ...";
1485*cdf0e10cSrcweir}
1486*cdf0e10cSrcweir
1487*cdf0e10cSrcweirsub usage
1488*cdf0e10cSrcweir{
1489*cdf0e10cSrcweir    my $exit_code = shift;
1490*cdf0e10cSrcweir    print STDERR "Usage:\ndeliver [OPTIONS] [DESTINATION-PATH]\n";
1491*cdf0e10cSrcweir    print STDERR "Options:\n";
1492*cdf0e10cSrcweir    print STDERR "  -check       just print what would happen, no actual copying of files\n";
1493*cdf0e10cSrcweir    print STDERR "  -checkdlst   be verbose about (possible) d.lst bugs\n";
1494*cdf0e10cSrcweir    print STDERR "  -delete      delete files (undeliver), use with care\n";
1495*cdf0e10cSrcweir    print STDERR "  -deloutput   remove the output tree after copying\n";
1496*cdf0e10cSrcweir    print STDERR "  -dontdeletecommon do not delete common files (for -delete option)\n";
1497*cdf0e10cSrcweir    print STDERR "  -force       copy even if not newer\n";
1498*cdf0e10cSrcweir    print STDERR "  -help        print this message\n";
1499*cdf0e10cSrcweir    if ( !defined($ENV{GUI}) || $ENV{GUI} ne 'WNT' ) {
1500*cdf0e10cSrcweir        print STDERR "  -link        hard link files into the solver to save disk space\n";
1501*cdf0e10cSrcweir    }
1502*cdf0e10cSrcweir    print STDERR "  -quiet       be quiet, only report errors\n";
1503*cdf0e10cSrcweir    print STDERR "  -verbose     be verbose\n";
1504*cdf0e10cSrcweir    print STDERR "  -zip         additionally create zip files of delivered content\n";
1505*cdf0e10cSrcweir    print STDERR "Options '-zip' and a destination-path are mutually exclusive.\n";
1506*cdf0e10cSrcweir    print STDERR "Options '-check' and '-quiet' are mutually exclusive.\n";
1507*cdf0e10cSrcweir    exit($exit_code);
1508*cdf0e10cSrcweir}
1509*cdf0e10cSrcweir
1510*cdf0e10cSrcweir# vim: set ts=4 shiftwidth=4 expandtab syntax=perl:
1511