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