Integrate change #12560 from maintperl;
[p5sagit/p5-mst-13.2.git] / win32 / bin / pl2bat.pl
CommitLineData
c9c878ae 1 eval 'exec perl -x -S "$0" ${1+"$@"}'
2 if 0; # In case running under some shell
3
d444a431 4require 5;
5use Getopt::Std;
c9c878ae 6use Config;
d444a431 7
8$0 =~ s|.*[/\\]||;
9
10my $usage = <<EOT;
c9c878ae 11Usage: $0 [-h]
12 or: $0 [-w] [-u] [-a argstring] [-s stripsuffix] [files]
13 or: $0 [-w] [-u] [-n ntargs] [-o otherargs] [-s stripsuffix] [files]
14 -n ntargs arguments to invoke perl with in generated file
15 when run from Windows NT. Defaults to
5a04aac4 16 '-x -S %0 %*'.
c9c878ae 17 -o otherargs arguments to invoke perl with in generated file
18 other than when run from Windows NT. Defaults
19 to '-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9'.
d444a431 20 -a argstring arguments to invoke perl with in generated file
c9c878ae 21 ignoring operating system (for compatibility
22 with previous pl2bat versions).
23 -u update files that may have already been processed
24 by (some version of) pl2bat.
25 -w include "-w" on the /^#!.*perl/ line (unless
26 a /^#!.*perl/ line was already present).
d444a431 27 -s stripsuffix strip this suffix from file before appending ".bat"
c9c878ae 28 Not case-sensitive
d444a431 29 Can be a regex if it begins with `/'
c9c878ae 30 Defaults to "/\.plx?/"
d444a431 31 -h show this help
32EOT
33
34my %OPT = ();
c9c878ae 35warn($usage), exit(0) if !getopts('whun:o:a:s:',\%OPT) or $OPT{'h'};
5a04aac4 36# NOTE: %0 is already enclosed in doublequotes by cmd.exe, as appropriate
37$OPT{'n'} = '-x -S %0 %*' unless exists $OPT{'n'};
c9c878ae 38$OPT{'o'} = '-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9' unless exists $OPT{'o'};
39$OPT{'s'} = '/\\.plx?/' unless exists $OPT{'s'};
ef0a8c2a 40$OPT{'s'} = ($OPT{'s'} =~ m#^/([^/]*[^/\$]|)\$?/?$# ? $1 : "\Q$OPT{'s'}\E");
d444a431 41
c9c878ae 42my $head;
43if( defined( $OPT{'a'} ) ) {
44 $head = <<EOT;
d444a431 45 \@rem = '--*-Perl-*--
46 \@echo off
47 perl $OPT{'a'}
48 goto endofperl
49 \@rem ';
50EOT
c9c878ae 51} else {
52 $head = <<EOT;
53 \@rem = '--*-Perl-*--
54 \@echo off
55 if "%OS%" == "Windows_NT" goto WinNT
56 perl $OPT{'o'}
57 goto endofperl
58 :WinNT
59 perl $OPT{'n'}
60 if NOT "%COMSPEC%" == "%SystemRoot%\\system32\\cmd.exe" goto endofperl
61 if %errorlevel% == 9009 echo You do not have Perl in your PATH.
ef0a8c2a 62 if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
c9c878ae 63 goto endofperl
64 \@rem ';
65EOT
66}
67$head =~ s/^\t//gm;
d444a431 68my $headlines = 2 + ($head =~ tr/\n/\n/);
517db077 69my $tail = "\n__END__\n:endofperl\n";
d444a431 70
71@ARGV = ('-') unless @ARGV;
72
c9c878ae 73foreach ( @ARGV ) {
74 process($_);
75}
d444a431 76
77sub process {
c9c878ae 78 my( $file )= @_;
79 my $myhead = $head;
80 my $linedone = 0;
81 my $taildone = 0;
82 my $linenum = 0;
83 my $skiplines = 0;
84 my $line;
a8ac1e79 85 my $start= $Config{startperl};
86 $start= "#!perl" unless $start =~ /^#!.*perl/;
c9c878ae 87 open( FILE, $file ) or die "$0: Can't open $file: $!";
88 @file = <FILE>;
89 foreach $line ( @file ) {
90 $linenum++;
91 if ( $line =~ /^:endofperl\b/ ) {
92 if( ! exists $OPT{'u'} ) {
93 warn "$0: $file has already been converted to a batch file!\n";
94 return;
d444a431 95 }
c9c878ae 96 $taildone++;
97 }
98 if ( not $linedone and $line =~ /^#!.*perl/ ) {
99 if( exists $OPT{'u'} ) {
100 $skiplines = $linenum - 1;
101 $line .= "#line ".(1+$headlines)."\n";
102 } else {
103 $line .= "#line ".($linenum+$headlines)."\n";
d444a431 104 }
c9c878ae 105 $linedone++;
106 }
107 if ( $line =~ /^#\s*line\b/ and $linenum == 2 + $skiplines ) {
108 $line = "";
109 }
d444a431 110 }
c9c878ae 111 close( FILE );
112 $file =~ s/$OPT{'s'}$//oi;
113 $file .= '.bat' unless $file =~ /\.bat$/i or $file =~ /^-$/;
114 open( FILE, ">$file" ) or die "Can't open $file: $!";
115 print FILE $myhead;
a8ac1e79 116 print FILE $start, ( $OPT{'w'} ? " -w" : "" ),
c9c878ae 117 "\n#line ", ($headlines+1), "\n" unless $linedone;
118 print FILE @file[$skiplines..$#file];
119 print FILE $tail unless $taildone;
120 close( FILE );
d444a431 121}
122__END__
123
124=head1 NAME
125
126pl2bat - wrap perl code into a batch file
127
128=head1 SYNOPSIS
129
c9c878ae 130B<pl2bat> B<-h>
131
132B<pl2bat> [B<-w>] S<[B<-a> I<argstring>]> S<[B<-s> I<stripsuffix>]> [files]
133
134B<pl2bat> [B<-w>] S<[B<-n> I<ntargs>]> S<[B<-o> I<otherargs>]> S<[B<-s> I<stripsuffix>]> [files]
d444a431 135
136=head1 DESCRIPTION
137
138This utility converts a perl script into a batch file that can be
ef0a8c2a 139executed on DOS-like operating systems. This is intended to allow
140you to use a Perl script like regular programs and batch files where
141you just enter the name of the script [probably minus the extension]
142plus any command-line arguments and the script is found in your B<PATH>
143and run.
d444a431 144
ef0a8c2a 145=head2 ADVANTAGES
146
147There are several alternatives to this method of running a Perl script.
148They each have disadvantages that help you understand the motivation
149for using B<pl2bat>.
150
151=over
152
153=item 1
154
155 C:> perl x:/path/to/script.pl [args]
156
157=item 2
158
159 C:> perl -S script.pl [args]
160
161=item 3
162
163 C:> perl -S script [args]
164
165=item 4
166
167 C:> ftype Perl=perl.exe "%1" %*
168 C:> assoc .pl=Perl
169 then
170 C:> script.pl [args]
171
172=item 5
173
174 C:> ftype Perl=perl.exe "%1" %*
175 C:> assoc .pl=Perl
176 C:> set PathExt=%PathExt%;.PL
177 then
178 C:> script [args]
179
180=back
181
182B<1> and B<2> are the most basic invocation methods that should work on
183any system [DOS-like or not]. They require extra typing and require
184that the script user know that the script is written in Perl. This
185is a pain when you have lots of scripts, some written in Perl and some
186not. It can be quite difficult to keep track of which scripts need to
187be run through Perl and which do not. Even worse, scripts often get
188rewritten from simple batch files into more powerful Perl scripts in
189which case these methods would require all existing users of the scripts
190be updated.
191
192B<3> works on modern Win32 versions of Perl. It allows the user to
193omit the ".pl" or ".bat" file extension, which is a minor improvement.
194
195B<4> and B<5> work on some Win32 operating systems with some command
196shells. One major disadvantage with both is that you can't use them
197in pipelines nor with file redirection. For example, none of the
198following will work properly if you used method B<4> or B<5>:
199
200 C:> script.pl <infile
201 C:> script.pl >outfile
202 C:> echo y | script.pl
203 C:> script.pl | more
204
205This is due to a Win32 bug which Perl has no control over. This bug
206is the major motivation for B<pl2bat> [which was originally written
207for DOS] being used on Win32 systems.
208
209Note also that B<5> works on a smaller range of combinations of Win32
210systems and command shells while B<4> requires that the user know
211that the script is a Perl script [because the ".pl" extension must
212be entered]. This makes it hard to standardize on either of these
213methods.
214
215=head2 DISADVANTAGES
216
217There are several potential traps you should be aware of when you
218use B<pl2bat>.
219
220The generated batch file is initially processed as a batch file each
221time it is run. This means that, to use it from within another batch
222file you should preceed it with C<call> or else the calling batch
223file will not run any commands after the script:
224
225 call script [args]
226
227Except under Windows NT, if you specify more than 9 arguments to
228the generated batch file then the 10th and subsequent arguments
229are silently ignored.
230
231Except when using F<CMD.EXE> under Windows NT, if F<perl.exe> is not
232in your B<PATH>, then trying to run the script will give you a generic
233"Command not found"-type of error message that will probably make you
234think that the script itself is not in your B<PATH>. When using
235F<CMD.EXE> under Windows NT, the generic error message is followed by
236"You do not have Perl in your PATH", to make this clearer.
237
238On most DOS-like operating systems, the only way to exit a batch file
239is to "fall off the end" of the file. B<pl2bat> implements this by
240doing C<goto :endofperl> and adding C<__END__> and C<:endofperl> as
241the last two lines of the generated batch file. This means:
242
243=over
244
245=item No line of your script should start with a colon.
246
247In particular, for this version of B<pl2bat>, C<:endofperl>,
248C<:WinNT>, and C<:script_failed_so_exit_with_non_zero_val> should not
249be used.
250
251=item Care must be taken when using C<__END__> and the C<DATA> file handle.
252
253One approach is:
254
a8c64e16 255 . #!perl
256 . while( <DATA> ) {
257 . last if /^__END__$/;
258 . [...]
259 . }
260 . __END__
261 . lines of data
262 . to be processed
263 . __END__
264 . :endofperl
265
266The dots in the first column are only there to prevent F<cmd.exe> to interpret
267the C<:endofperl> line in this documentation. Otherwise F<pl2bat.bat> itself
268wouldn't work. See the previous item. :-)
ef0a8c2a 269
270=item The batch file always "succeeds"
271
272The following commands illustrate the problem:
273
274 C:> echo exit(99); >fail.pl
275 C:> pl2bat fail.pl
276 C:> perl -e "print system('perl fail.pl')"
277 99
278 C:> perl -e "print system('fail.bat')"
279 0
280
281So F<fail.bat> always reports that it completed successfully. Actually,
282under Windows NT, we have:
283
284 C:> perl -e "print system('fail.bat')"
285 1
286
287So, for Windows NT, F<fail.bat> fails when the Perl script fails, but
288the return code is always C<1>, not the return code from the Perl script.
289
290=back
291
292=head2 FUNCTION
293
294By default, the ".pl" suffix will be stripped before adding a ".bat" suffix
295to the supplied file names. This can be controlled with the C<-s> option.
d444a431 296
c9c878ae 297The default behavior is to have the batch file compare the C<OS>
298environment variable against C<"Windows_NT">. If they match, it
d444a431 299uses the C<%*> construct to refer to all the command line arguments
300that were given to it, so you'll need to make sure that works on your
ef0a8c2a 301variant of the command shell. It is known to work in the F<CMD.EXE> shell
302under Windows NT. 4DOS/NT users will want to put a C<ParameterChar = *>
d444a431 303line in their initialization file, or execute C<setdos /p*> in
c9c878ae 304the shell startup file.
305
306On Windows95 and other platforms a nine-argument limit is imposed
307on command-line arguments given to the generated batch file, since
308they may not support C<%*> in batch files.
309
310These can be overridden using the C<-n> and C<-o> options or the
311deprecated C<-a> option.
d444a431 312
313=head1 OPTIONS
314
315=over 8
316
c9c878ae 317=item B<-n> I<ntargs>
318
319Arguments to invoke perl with in generated batch file when run from
5a04aac4 320Windows NT (or Windows 98, probably). Defaults to S<'-x -S %0 %*'>.
c9c878ae 321
322=item B<-o> I<otherargs>
323
324Arguments to invoke perl with in generated batch file except when
325run from Windows NT (ie. when run from DOS, Windows 3.1, or Windows 95).
326Defaults to S<'-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9'>.
327
d444a431 328=item B<-a> I<argstring>
329
c9c878ae 330Arguments to invoke perl with in generated batch file. Specifying
331B<-a> prevents the batch file from checking the C<OS> environment
332variable to determine which operating system it is being run from.
d444a431 333
334=item B<-s> I<stripsuffix>
335
336Strip a suffix string from file name before appending a ".bat"
c9c878ae 337suffix. The suffix is not case-sensitive. It can be a regex if
338it begins with `/' (the trailing '/' is optional and a trailing
339C<$> is always assumed). Defaults to C</.plx?/>.
340
341=item B<-w>
342
343If no line matching C</^#!.*perl/> is found in the script, then such
344a line is inserted just after the new preamble. The exact line
345depends on C<$Config{startperl}> [see L<Config>]. With the B<-w>
346option, C<" -w"> is added after the value of C<$Config{startperl}>.
347If a line matching C</^#!.*perl/> already exists in the script,
348then it is not changed and the B<-w> option is ignored.
349
350=item B<-u>
351
352If the script appears to have already been processed by B<pl2bat>,
353then the script is skipped and not processed unless B<-u> was
354specified. If B<-u> is specified, the existing preamble is replaced.
d444a431 355
356=item B<-h>
357
358Show command line usage.
359
360=back
361
362=head1 EXAMPLES
363
364 C:\> pl2bat foo.pl bar.PM
365 [..creates foo.bat, bar.PM.bat..]
366
367 C:\> pl2bat -s "/\.pl|\.pm/" foo.pl bar.PM
368 [..creates foo.bat, bar.bat..]
369
370 C:\> pl2bat < somefile > another.bat
371
372 C:\> pl2bat > another.bat
373 print scalar reverse "rekcah lrep rehtona tsuj\n";
374 ^Z
375 [..another.bat is now a certified japh application..]
c9c878ae 376
377 C:\> ren *.bat *.pl
378 C:\> pl2bat -u *.pl
379 [..updates the wrapping of some previously wrapped scripts..]
380
381 C:\> pl2bat -u -s .bat *.bat
382 [..same as previous example except more dangerous..]
d444a431 383
384=head1 BUGS
385
386C<$0> will contain the full name, including the ".bat" suffix
387when the generated batch file runs. If you don't like this,
388see runperl.bat for an alternative way to invoke perl scripts.
389
c9c878ae 390Default behavior is to invoke Perl with the B<-S> flag, so Perl will
ef0a8c2a 391search the B<PATH> to find the script. This may have undesirable
d444a431 392effects.
393
ef0a8c2a 394On really old versions of Win32 Perl, you can't run the script
395via
396
397 C:> script.bat [args]
398
399and must use
400
401 C:> script [args]
402
403A loop should be used to build up the argument list when not on
404Windows NT so more than 9 arguments can be processed.
405
406See also L</Disadvantages>.
407
d444a431 408=head1 SEE ALSO
409
410perl, perlwin32, runperl.bat
411
412=cut
413