This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Corrections to spelling and grammatical errors.
[perl5.git] / win32 / bin / pl2bat.pl
CommitLineData
c9c878ae
TM
1 eval 'exec perl -x -S "$0" ${1+"$@"}'
2 if 0; # In case running under some shell
3
d444a431
TB
4require 5;
5use Getopt::Std;
c9c878ae 6use Config;
d444a431
TB
7
8$0 =~ s|.*[/\\]||;
9
10my $usage = <<EOT;
c9c878ae
TM
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
TM
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
TM
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
c2b27382 29 Can be a regex if it begins with '/'
c9c878ae 30 Defaults to "/\.plx?/"
d444a431
TB
31 -h show this help
32EOT
33
34my %OPT = ();
c9c878ae 35warn($usage), exit(0) if !getopts('whun:o:a:s:',\%OPT) or $OPT{'h'};
f5323a25 36# NOTE: %0 is already enclosed in double quotes by cmd.exe, as appropriate
5a04aac4 37$OPT{'n'} = '-x -S %0 %*' unless exists $OPT{'n'};
c9c878ae
TM
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
TM
42my $head;
43if( defined( $OPT{'a'} ) ) {
44 $head = <<EOT;
d444a431
TB
45 \@rem = '--*-Perl-*--
46 \@echo off
47 perl $OPT{'a'}
48 goto endofperl
49 \@rem ';
50EOT
c9c878ae
TM
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
TM
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
TB
70
71@ARGV = ('-') unless @ARGV;
72
c9c878ae
TM
73foreach ( @ARGV ) {
74 process($_);
75}
d444a431
TB
76
77sub process {
c9c878ae
TM
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
GS
85 my $start= $Config{startperl};
86 $start= "#!perl" unless $start =~ /^#!.*perl/;
c9c878ae
TM
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
TM
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
TM
105 $linedone++;
106 }
107 if ( $line =~ /^#\s*line\b/ and $linenum == 2 + $skiplines ) {
108 $line = "";
109 }
d444a431 110 }
c9c878ae
TM
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
TM
117 "\n#line ", ($headlines+1), "\n" unless $linedone;
118 print FILE @file[$skiplines..$#file];
119 print FILE $tail unless $taildone;
120 close( FILE );
d444a431
TB
121}
122__END__
123
124=head1 NAME
125
126pl2bat - wrap perl code into a batch file
127
128=head1 SYNOPSIS
129
c9c878ae
TM
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
TB
135
136=head1 DESCRIPTION
137
138This utility converts a perl script into a batch file that can be
ef0a8c2a
TM
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
TM
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
3c4b39be 222file you should precede it with C<call> or else the calling batch
ef0a8c2a
TM
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
JD
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
TM
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
TM
297The default behavior is to have the batch file compare the C<OS>
298environment variable against C<"Windows_NT">. If they match, it
d444a431
TB
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
TM
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
TM
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
TB
312
313=head1 OPTIONS
314
315=over 8
316
c9c878ae
TM
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
TM
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
TB
328=item B<-a> I<argstring>
329
c9c878ae
TM
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
TB
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
c2b27382 338it begins with '/' (the trailing '/' is optional and a trailing
c9c878ae
TM
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
TB
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..]
f703fc96 366
d444a431
TB
367 C:\> pl2bat -s "/\.pl|\.pm/" foo.pl bar.PM
368 [..creates foo.bat, bar.bat..]
f703fc96 369
d444a431 370 C:\> pl2bat < somefile > another.bat
f703fc96 371
d444a431
TB
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..]
f703fc96 376
c9c878ae
TM
377 C:\> ren *.bat *.pl
378 C:\> pl2bat -u *.pl
379 [..updates the wrapping of some previously wrapped scripts..]
f703fc96 380
c9c878ae
TM
381 C:\> pl2bat -u -s .bat *.bat
382 [..same as previous example except more dangerous..]
d444a431
TB
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
TB
392effects.
393
ef0a8c2a
TM
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
64da3008 406See also L</DISADVANTAGES>.
ef0a8c2a 407
d444a431
TB
408=head1 SEE ALSO
409
410perl, perlwin32, runperl.bat
411
412=cut
413