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