This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix various minor pod issues
[perl5.git] / win32 / bin / pl2bat.pl
1     eval 'exec perl -x -S "$0" ${1+"$@"}'
2         if 0;   # In case running under some shell
3
4 require 5;
5 use Getopt::Std;
6 use Config;
7
8 $0 =~ s|.*[/\\]||;
9
10 my $usage = <<EOT;
11 Usage:  $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
16                             '-x -S %0 %*'.
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'.
20         -a argstring    arguments to invoke perl with in generated file
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).
27         -s stripsuffix  strip this suffix from file before appending ".bat"
28                             Not case-sensitive
29                             Can be a regex if it begins with '/'
30                             Defaults to "/\.plx?/"
31         -h              show this help
32 EOT
33
34 my %OPT = ();
35 warn($usage), exit(0) if !getopts('whun:o:a:s:',\%OPT) or $OPT{'h'};
36 # NOTE: %0 is already enclosed in doublequotes by cmd.exe, as appropriate
37 $OPT{'n'} = '-x -S %0 %*' unless exists $OPT{'n'};
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'};
40 $OPT{'s'} = ($OPT{'s'} =~ m#^/([^/]*[^/\$]|)\$?/?$# ? $1 : "\Q$OPT{'s'}\E");
41
42 my $head;
43 if(  defined( $OPT{'a'} )  ) {
44     $head = <<EOT;
45         \@rem = '--*-Perl-*--
46         \@echo off
47         perl $OPT{'a'}
48         goto endofperl
49         \@rem ';
50 EOT
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.
62         if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
63         goto endofperl
64         \@rem ';
65 EOT
66 }
67 $head =~ s/^\t//gm;
68 my $headlines = 2 + ($head =~ tr/\n/\n/);
69 my $tail = "\n__END__\n:endofperl\n";
70
71 @ARGV = ('-') unless @ARGV;
72
73 foreach ( @ARGV ) {
74     process($_);
75 }
76
77 sub process {
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;
85     my $start= $Config{startperl};
86     $start= "#!perl"   unless  $start =~ /^#!.*perl/;
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;
95             }
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";
104             }
105             $linedone++;
106         }
107         if ( $line =~ /^#\s*line\b/ and $linenum == 2 + $skiplines ) {
108             $line = "";
109         }
110     }
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;
116     print FILE $start, ( $OPT{'w'} ? " -w" : "" ),
117                "\n#line ", ($headlines+1), "\n" unless $linedone;
118     print FILE @file[$skiplines..$#file];
119     print FILE $tail unless $taildone;
120     close( FILE );
121 }
122 __END__
123
124 =head1 NAME
125
126 pl2bat - wrap perl code into a batch file
127
128 =head1 SYNOPSIS
129
130 B<pl2bat> B<-h>
131
132 B<pl2bat> [B<-w>] S<[B<-a> I<argstring>]> S<[B<-s> I<stripsuffix>]> [files]
133
134 B<pl2bat> [B<-w>] S<[B<-n> I<ntargs>]> S<[B<-o> I<otherargs>]> S<[B<-s> I<stripsuffix>]> [files]
135
136 =head1 DESCRIPTION
137
138 This utility converts a perl script into a batch file that can be
139 executed on DOS-like operating systems.  This is intended to allow
140 you to use a Perl script like regular programs and batch files where
141 you just enter the name of the script [probably minus the extension]
142 plus any command-line arguments and the script is found in your B<PATH>
143 and run.
144
145 =head2 ADVANTAGES
146
147 There are several alternatives to this method of running a Perl script. 
148 They each have disadvantages that help you understand the motivation
149 for 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
182 B<1> and B<2> are the most basic invocation methods that should work on
183 any system [DOS-like or not].  They require extra typing and require
184 that the script user know that the script is written in Perl.  This
185 is a pain when you have lots of scripts, some written in Perl and some
186 not.  It can be quite difficult to keep track of which scripts need to
187 be run through Perl and which do not.  Even worse, scripts often get
188 rewritten from simple batch files into more powerful Perl scripts in
189 which case these methods would require all existing users of the scripts
190 be updated.
191
192 B<3> works on modern Win32 versions of Perl.  It allows the user to
193 omit the ".pl" or ".bat" file extension, which is a minor improvement.
194
195 B<4> and B<5> work on some Win32 operating systems with some command
196 shells.  One major disadvantage with both is that you can't use them
197 in pipelines nor with file redirection.  For example, none of the
198 following 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
205 This is due to a Win32 bug which Perl has no control over.  This bug
206 is the major motivation for B<pl2bat> [which was originally written
207 for DOS] being used on Win32 systems.
208
209 Note also that B<5> works on a smaller range of combinations of Win32
210 systems and command shells while B<4> requires that the user know
211 that the script is a Perl script [because the ".pl" extension must
212 be entered].  This makes it hard to standardize on either of these
213 methods.
214
215 =head2 DISADVANTAGES
216
217 There are several potential traps you should be aware of when you
218 use B<pl2bat>.
219
220 The generated batch file is initially processed as a batch file each
221 time it is run.  This means that, to use it from within another batch
222 file you should precede it with C<call> or else the calling batch
223 file will not run any commands after the script:
224
225     call script [args]
226
227 Except under Windows NT, if you specify more than 9 arguments to
228 the generated batch file then the 10th and subsequent arguments
229 are silently ignored.
230
231 Except when using F<CMD.EXE> under Windows NT, if F<perl.exe> is not
232 in 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
234 think that the script itself is not in your B<PATH>.  When using
235 F<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
238 On most DOS-like operating systems, the only way to exit a batch file
239 is to "fall off the end" of the file.  B<pl2bat> implements this by
240 doing C<goto :endofperl> and adding C<__END__> and C<:endofperl> as
241 the 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
247 In particular, for this version of B<pl2bat>, C<:endofperl>,
248 C<:WinNT>, and C<:script_failed_so_exit_with_non_zero_val> should not
249 be used.
250
251 =item Care must be taken when using C<__END__> and the C<DATA> file handle.
252
253 One approach is:
254
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
266 The dots in the first column are only there to prevent F<cmd.exe> to interpret
267 the C<:endofperl> line in this documentation.  Otherwise F<pl2bat.bat> itself
268 wouldn't work.  See the previous item. :-)
269
270 =item The batch file always "succeeds"
271
272 The 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
281 So F<fail.bat> always reports that it completed successfully.  Actually,
282 under Windows NT, we have:
283
284     C:> perl -e "print system('fail.bat')"
285     1
286
287 So, for Windows NT, F<fail.bat> fails when the Perl script fails, but
288 the return code is always C<1>, not the return code from the Perl script.
289
290 =back
291
292 =head2 FUNCTION
293
294 By default, the ".pl" suffix will be stripped before adding a ".bat" suffix
295 to the supplied file names.  This can be controlled with the C<-s> option.
296
297 The default behavior is to have the batch file compare the C<OS>
298 environment variable against C<"Windows_NT">.  If they match, it
299 uses the C<%*> construct to refer to all the command line arguments
300 that were given to it, so you'll need to make sure that works on your
301 variant of the command shell.  It is known to work in the F<CMD.EXE> shell
302 under Windows NT.  4DOS/NT users will want to put a C<ParameterChar = *>
303 line in their initialization file, or execute C<setdos /p*> in
304 the shell startup file.
305
306 On Windows95 and other platforms a nine-argument limit is imposed
307 on command-line arguments given to the generated batch file, since
308 they may not support C<%*> in batch files.
309
310 These can be overridden using the C<-n> and C<-o> options or the
311 deprecated C<-a> option.
312
313 =head1 OPTIONS
314
315 =over 8
316
317 =item B<-n> I<ntargs>
318
319 Arguments to invoke perl with in generated batch file when run from
320 Windows NT (or Windows 98, probably).  Defaults to S<'-x -S %0 %*'>.
321
322 =item B<-o> I<otherargs>
323
324 Arguments to invoke perl with in generated batch file except when
325 run from Windows NT (ie. when run from DOS, Windows 3.1, or Windows 95).
326 Defaults to S<'-x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9'>.
327
328 =item B<-a> I<argstring>
329
330 Arguments to invoke perl with in generated batch file.  Specifying
331 B<-a> prevents the batch file from checking the C<OS> environment
332 variable to determine which operating system it is being run from.
333
334 =item B<-s> I<stripsuffix>
335
336 Strip a suffix string from file name before appending a ".bat"
337 suffix.  The suffix is not case-sensitive.  It can be a regex if
338 it begins with '/' (the trailing '/' is optional and a trailing
339 C<$> is always assumed).  Defaults to C</.plx?/>.
340
341 =item B<-w>
342
343 If no line matching C</^#!.*perl/> is found in the script, then such
344 a line is inserted just after the new preamble.  The exact line
345 depends on C<$Config{startperl}> [see L<Config>].  With the B<-w>
346 option, C<" -w"> is added after the value of C<$Config{startperl}>.
347 If a line matching C</^#!.*perl/> already exists in the script,
348 then it is not changed and the B<-w> option is ignored.
349
350 =item B<-u>
351
352 If the script appears to have already been processed by B<pl2bat>,
353 then the script is skipped and not processed unless B<-u> was
354 specified.  If B<-u> is specified, the existing preamble is replaced.
355
356 =item B<-h>
357
358 Show 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..]
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..]
383
384 =head1 BUGS
385
386 C<$0> will contain the full name, including the ".bat" suffix
387 when the generated batch file runs.  If you don't like this,
388 see runperl.bat for an alternative way to invoke perl scripts.
389
390 Default behavior is to invoke Perl with the B<-S> flag, so Perl will
391 search the B<PATH> to find the script.   This may have undesirable
392 effects.
393
394 On really old versions of Win32 Perl, you can't run the script
395 via
396
397     C:> script.bat [args]
398
399 and must use
400
401     C:> script [args]
402
403 A loop should be used to build up the argument list when not on
404 Windows NT so more than 9 arguments can be processed.
405
406 See also L</DISADVANTAGES>.
407
408 =head1 SEE ALSO
409
410 perl, perlwin32, runperl.bat
411
412 =cut
413