4 use File::Basename qw(basename dirname);
7 # List explicitly here the variables you want Configure to
8 # generate. Metaconfig only looks for shell variables, so you
9 # have to mention them as if they were shell variables, not
10 # %Config entries. Thus you write
12 # to ensure Configure will look for $Config{startperl}.
15 # This forces PL files to create target in same directory as PL file.
16 # This is so that make depend always knows where to find PL derivatives.
19 $file = basename($0, '.PL');
20 $file .= '.com' if $^O eq 'VMS';
22 open OUT,">$file" or die "Can't create $file: $!";
24 print "Extracting $file (with variable substitutions)\n";
26 # In this section, perl variables will be expanded during extraction.
27 # You can use $Config{...} to use Configure variables.
29 print OUT <<"!GROK!THIS!";
31 eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
32 if \$running_under_some_shell;
35 # In the following, perl variables are not expanded during extraction.
37 print OUT <<'!NO!SUBS!';
42 use File::Path qw(mkpath);
45 # Make sure read permissions for all are set:
46 if (defined umask && (umask() & 0444)) {
47 umask (umask() & ~0444);
51 use vars qw($opt_D $opt_d $opt_r $opt_l $opt_h $opt_a $opt_Q $opt_e);
52 die "-r and -a options are mutually exclusive\n" if ($opt_r and $opt_a);
53 my @inc_dirs = inc_dirs() if $opt_a;
57 my $Dest_dir = $opt_d || $Config{installsitearch};
58 die "Destination directory $Dest_dir doesn't exist or isn't a directory\n"
61 my @isatype = split(' ',<<END);
70 @isatype{@isatype} = (1) x @isatype;
75 @ARGV = ('-') unless @ARGV;
77 build_preamble_if_necessary();
86 my ($t, $tab, %curargs, $new, $eval_index, $dir, $name, $args, $outfile);
87 my ($incl, $incl_type, $next);
88 while (defined (my $file = next_file())) {
89 if (-l $file and -d $file) {
90 link_if_possible($file) if ($opt_l);
94 # Recover from header files with unbalanced cpp directives
98 # $eval_index goes into ``#line'' directives, to help locate syntax errors:
105 ($outfile = $file) =~ s/\.h$/.ph/ || next;
106 print "$file -> $outfile\n" unless $opt_Q;
107 if ($file =~ m|^(.*)/|) {
109 mkpath "$Dest_dir/$dir";
112 if ($opt_a) { # automagic mode: locate header file in @inc_dirs
113 foreach (@inc_dirs) {
119 open(IN,"$file") || (($Exit = 1),(warn "Can't open $file: $!\n"),next);
120 open(OUT,">$Dest_dir/$outfile") || die "Can't create $outfile: $!\n";
124 "require '_h2ph_pre.ph';\n\n",
125 "no warnings 'redefine';\n\n";
127 while (defined (local $_ = next_line($file))) {
129 if (s/^define\s+(\w+)//) {
133 s/\(\w+\s*\(\*\)\s*\(\w*\)\)\s*(-?\d+)/$1/; # (int (*)(foo_t))0
134 if (s/^\(([\w,\s]*)\)//) {
139 foreach my $arg (split(/,\s*/,$args)) {
140 $arg =~ s/^\s*([^\s].*[^\s])\s*$/$1/;
143 $args =~ s/\b(\w)/\$$1/g;
144 $args = "local($args) = \@_;\n$t ";
148 $new =~ s/(["\\])/\\$1/g; #"]);
149 $new = reindent($new);
150 $args = reindent($args);
152 $new =~ s/(['\\])/\\$1/g; #']);
155 "eval \"\\n#line $eval_index $outfile\\n\" . 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
159 "eval 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
162 print OUT "unless(defined(\&$name)) {\n sub $name $proto\{\n\t${args}eval q($new);\n }\n}\n";
168 $new = 1 if $new eq '';
169 $new = reindent($new);
170 $args = reindent($args);
172 $new =~ s/(['\\])/\\$1/g; #']);
175 print OUT $t,"eval \"\\n#line $eval_index $outfile\\n\" . 'sub $name () {",$new,";}' unless defined(\&$name);\n";
178 print OUT $t,"eval 'sub $name () {",$new,";}' unless defined(\&$name);\n";
181 # Shunt around such directives as `#define FOO FOO':
182 next if " \&$name" eq $new;
184 print OUT $t,"unless(defined(\&$name)) {\n sub $name () {\t",$new,";}\n}\n";
187 } elsif (/^(include|import|include_next)\s*[<\"](.*)[>\"]/) {
190 if (($incl_type eq 'include_next') ||
191 ($opt_e && exists($bad_file{$incl}))) {
192 $incl =~ s/\.h$/.ph/;
196 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
197 print OUT ($t, "my(\@REM);\n");
198 if ($incl_type eq 'include_next') {
200 "my(\%INCD) = map { \$INC{\$_} => 1 } ",
201 "(grep { \$_ eq \"$incl\" } ",
204 "\@REM = map { \"\$_/$incl\" } ",
205 "(grep { not exists(\$INCD{\"\$_/$incl\"})",
206 " and -f \"\$_/$incl\" } \@INC);\n");
209 "\@REM = map { \"\$_/$incl\" } ",
210 "(grep {-r \"\$_/$incl\" } \@INC);\n");
213 "require \"\$REM[0]\" if \@REM;\n");
215 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
219 "warn(\$\@) if \$\@;\n");
221 $incl =~ s/\.h$/.ph/;
222 print OUT $t,"require '$incl';\n";
224 } elsif (/^ifdef\s+(\w+)/) {
225 print OUT $t,"if(defined(&$1)) {\n";
227 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
228 } elsif (/^ifndef\s+(\w+)/) {
229 print OUT $t,"unless(defined(&$1)) {\n";
231 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
232 } elsif (s/^if\s+//) {
237 print OUT $t,"if($new) {\n";
239 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
240 } elsif (s/^elif\s+//) {
246 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
247 print OUT $t,"}\n elsif($new) {\n";
249 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
252 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
253 print OUT $t,"} else {\n";
255 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
258 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
260 } elsif(/^undef\s+(\w+)/) {
261 print OUT $t, "undef(&$1) if defined(&$1);\n";
262 } elsif(/^error\s+(".*")/) {
263 print OUT $t, "die($1);\n";
264 } elsif(/^error\s+(.*)/) {
265 print OUT $t, "die(\"", quotemeta($1), "\");\n";
266 } elsif(/^warning\s+(.*)/) {
267 print OUT $t, "warn(\"", quotemeta($1), "\");\n";
268 } elsif(/^ident\s+(.*)/) {
269 print OUT $t, "# $1\n";
271 } elsif (/^\s*(typedef\s*)?enum\s*(\s+[a-zA-Z_]\w*\s*)?/) { # { for vi
272 until(/\{[^}]*\}.*;/ || /;/) {
273 last unless defined ($next = next_line($file));
275 # drop "#define FOO FOO" in enums
276 $next =~ s/^\s*#\s*define\s+(\w+)\s+\1\s*$//;
278 print OUT "# $next\n" if $opt_D;
280 s/#\s*if.*?#\s*endif//g; # drop #ifdefs
283 next unless /^\s?(typedef\s?)?enum\s?([a-zA-Z_]\w*)?\s?\{(.*)\}\s?([a-zA-Z_]\w*)?\s?;/;
284 (my $enum_subs = $3) =~ s/\s//g;
285 my @enum_subs = split(/,/, $enum_subs);
287 foreach my $enum (@enum_subs) {
288 my ($enum_name, $enum_value) = $enum =~ /^([a-zA-Z_]\w*)(=.+)?$/;
289 $enum_value =~ s/^=//;
290 $enum_val = (length($enum_value) ? $enum_value : $enum_val + 1);
293 "eval(\"\\n#line $eval_index $outfile\\n",
294 "sub $enum_name () \{ $enum_val; \}\") ",
295 "unless defined(\&$enum_name);\n");
299 "eval(\"sub $enum_name () \{ $enum_val; \}\") ",
300 "unless defined(\&$enum_name);\n");
303 } elsif (/^(?:__extension__\s+)?extern\s+__inline(?:__)?\s+/) { # { for vi
304 # This is a hack to parse the inline functions in the glibc headers.
305 # Warning: massive kludge ahead. We suppose inline functions are mainly
306 # constructed like macros.
308 last unless defined ($next = next_line($file));
310 undef $_, last if $next =~ /__THROW\s*;/;
312 print OUT "# $next\n" if $opt_D;
313 last if $next =~ /^}|^{.*}\s*$/;
315 next if not defined; # because it's only a prototype
316 s/\b(__extension__|extern|__inline(?:__)?)\b//g;
317 if (s/^(?:\w|\s|\*)*\s(\w+)\s*//) {
320 warn "name not found"; next; # shouldn't occur...
323 if (s/^\(([^()]*)\)\s*(\w+\s*)*//) {
324 for my $arg (split /,/, $1) {
325 if ($arg =~ /(\w+)\s*$/) {
333 ? "local(" . (join ',', map "\$$_", @args) . ") = \@_;\n$t "
336 my $proto = @args ? '' : '() ';
338 s/\breturn\b//g; # "return" doesn't occur in macros usually...
340 $new =~ s/(["\\])/\\$1/g; #"]);
341 $new = reindent($new);
342 $args = reindent($args);
344 $new =~ s/(['\\])/\\$1/g; #']);
347 "eval \"\\n#line $eval_index $outfile\\n\" . 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
351 "eval 'sub $name $proto\{\n$t ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
354 print OUT "unless(defined(\&$name)) {\n sub $name $proto\{\n\t${args}eval q($new);\n }\n}\n";
359 $Is_converted{$file} = 1;
360 if ($opt_e && exists($bad_file{$file})) {
361 unlink($Dest_dir . '/' . $outfile);
365 queue_includes_from($file) if $opt_a;
369 if ($opt_e && (scalar(keys %bad_file) > 0)) {
370 warn "Was unable to convert the following files:\n";
371 warn "\t" . join("\n\t",sort(keys %bad_file)) . "\n";
379 $joined_args = join('|', keys(%curargs));
382 s/^\&\&// && do { $new .= " &&"; next;}; # handle && operator
383 s/^\&([\(a-z\)]+)/$1/i; # hack for things that take the address of
384 s/^(\s+)// && do {$new .= ' '; next;};
385 s/^0X([0-9A-F]+)[UL]*//i
388 if (length $hex > 8 && !$Config{use64bitint}) {
389 # Croak if nv_preserves_uv_bits < 64 ?
390 $new .= hex(substr($hex, -8)) +
391 2**32 * hex(substr($hex, 0, -8));
392 # The above will produce "errorneus" code
393 # if the hex constant was e.g. inside UINT64_C
394 # macro, but then again, h2ph is an approximation.
396 $new .= lc("0x$hex");
399 s/^(-?\d+\.\d+E[-+]?\d+)[FL]?//i && do {$new .= $1; next;};
400 s/^(\d+)\s*[LU]*//i && do {$new .= $1; next;};
401 s/^("(\\"|[^"])*")// && do {$new .= $1; next;};
402 s/^'((\\"|[^"])*)'// && do {
404 $new .= "ord('\$$1')";
410 # replace "sizeof(foo)" with "{foo}"
411 # also, remove * (C dereference operator) to avoid perl syntax
412 # problems. Where the %sizeof array comes from is anyone's
413 # guess (c2ph?), but this at least avoids fatal syntax errors.
414 # Behavior is undefined if sizeof() delimiters are unbalanced.
415 # This code was modified to able to handle constructs like this:
416 # sizeof(*(p)), which appear in the HP-UX 10.01 header files.
417 s/^sizeof\s*\(// && do {
419 my $lvl = 1; # already saw one open paren
420 # tack { on the front, and skip it in the loop
423 # find balanced closing paren
424 while ($index <= length($_) && $lvl > 0) {
425 $lvl++ if substr($_, $index, 1) eq "(";
426 $lvl-- if substr($_, $index, 1) eq ")";
429 # tack } on the end, replacing )
430 substr($_, $index - 1, 1) = "}";
431 # remove pesky * operators within the sizeof argument
432 substr($_, 0, $index - 1) =~ s/\*//g;
436 /\(([\w\s]+)[\*\s]*\)\s*[\w\(]/ && do {
438 foreach (split /\s+/, $1) { # Make sure all the words are types,
439 unless($isatype{$_} or $_ eq 'struct' or $_ eq 'union'){
445 s/\([\w\s]+[\*\s]*\)// && next; # then eliminate them.
448 # struct/union member, including arrays:
449 s/^([_A-Z]\w*(\[[^\]]+\])?((\.|->)[_A-Z]\w*(\[[^\]]+\])?)+)//i && do {
451 $id =~ s/(\.|(->))([^\.\-]*)/->\{$3\}/g;
452 $id =~ s/\b([^\$])($joined_args)/$1\$$2/g if length($joined_args);
453 while($id =~ /\[\s*([^\$\&\d\]]+)\]/) {
456 if(exists($curargs{$index})) {
461 $id =~ s/\[\s*([^\$\&\d\]]+)\]/[$index]/;
465 s/^([_a-zA-Z]\w*)// && do {
467 if ($id eq 'struct' || $id eq 'union') {
471 } elsif ($id =~ /^((un)?signed)|(long)|(short)$/) {
472 while (s/^\s+(\w+)//) { $id .= ' ' . $1; }
477 $new .= '->' if /^[\[\{]/;
478 } elsif ($id eq 'defined') {
481 s/^\s*\((\w),/("$1",/ if $id =~ /^_IO[WR]*$/i; # cheat
483 } elsif ($isatype{$id}) {
484 if ($new =~ /{\s*$/) {
486 } elsif ($new =~ /\(\s*$/ && /^[\s*]*\)/) {
490 $new .= q(').$id.q(');
493 if ($inif && $new !~ /defined\s*\($/) {
494 $new .= '(defined(&' . $id . ') ? &' . $id . ' : 0)';
503 s/^(.)// && do { if ($1 ne '#') { $new .= $1; } next;};
512 my $pre_sub_tri_graphs = 1;
514 READ: while (not eof IN) {
517 next unless length $in;
520 if ($pre_sub_tri_graphs) {
521 # Preprocess all tri-graphs
522 # including things stuck in quoted string constants.
523 $in =~ s/\?\?=/#/g; # | ??=| #|
524 $in =~ s/\?\?\!/|/g; # | ??!| ||
525 $in =~ s/\?\?'/^/g; # | ??'| ^|
526 $in =~ s/\?\?\(/[/g; # | ??(| [|
527 $in =~ s/\?\?\)/]/g; # | ??)| ]|
528 $in =~ s/\?\?\-/~/g; # | ??-| ~|
529 $in =~ s/\?\?\//\\/g; # | ??/| \|
530 $in =~ s/\?\?</{/g; # | ??<| {|
531 $in =~ s/\?\?>/}/g; # | ??>| }|
533 if ($in =~ /^\#ifdef __LANGUAGE_PASCAL__/) {
534 # Tru64 disassembler.h evilness: mixed C and Pascal.
540 if ($in =~ /^extern inline / && # Inlined assembler.
541 $^O eq 'linux' && $file =~ m!(?:^|/)asm/[^/]+\.h$!) {
547 if ($in =~ s/\\$//) { # \-newline
550 } elsif ($in =~ s/^([^"'\\\/]+)//) { # Passthrough
552 } elsif ($in =~ s/^(\\.)//) { # \...
554 } elsif ($in =~ /^'/) { # '...
555 if ($in =~ s/^('(\\.|[^'\\])*')//) {
560 } elsif ($in =~ /^"/) { # "...
561 if ($in =~ s/^("(\\.|[^"\\])*")//) {
566 } elsif ($in =~ s/^\/\/.*//) { # //...
568 } elsif ($in =~ m/^\/\*/) { # /*...
569 # C comment removal adapted from perlfaq6:
570 if ($in =~ s/^\/\*[^*]*\*+([^\/*][^*]*\*+)*\///) {
572 } else { # Incomplete /* */
575 } elsif ($in =~ s/^(\/)//) { # /...
577 } elsif ($in =~ s/^([^\'\"\\\/]+)//) {
579 } elsif ($^O eq 'linux' &&
580 $file =~ m!(?:^|/)linux/byteorder/pdp_endian\.h$! &&
581 $in =~ s!\'T KNOW!!) {
582 $out =~ s!I DON$!I_DO_NOT_KNOW!;
585 warn "Cannot parse $file:\n$in\n";
586 $bad_file{$file} = 1;
591 die "Cannot parse:\n$in\n";
596 last READ if $out =~ /\S/;
603 # Handle recursive subdirectories without getting a grotesquely big stack.
604 # Could this be implemented using File::Find?
612 if ($file eq '-' or -f $file or -l $file) {
618 print STDERR "Skipping directory `$file'\n";
623 print STDERR "Skipping `$file': not a file or directory\n";
631 # Put all the files in $directory into @ARGV for processing.
634 my ($directory) = @_;
636 $directory =~ s:/$::;
638 opendir DIR, $directory;
639 foreach (readdir DIR) {
640 next if ($_ eq '.' or $_ eq '..');
642 # expand_glob() is going to be called until $ARGV[0] isn't a
643 # directory; so push directories, and unshift everything else.
644 if (-d "$directory/$_") { push @ARGV, "$directory/$_" }
645 else { unshift @ARGV, "$directory/$_" }
651 # Given $file, a symbolic link to a directory in the C include directory,
652 # make an equivalent symbolic link in $Dest_dir, if we can figure out how.
653 # Otherwise, just duplicate the file or directory.
657 my $target = eval 'readlink($dirlink)';
659 if ($target =~ m:^\.\./: or $target =~ m:^/:) {
660 # The target of a parent or absolute link could leave the $Dest_dir
661 # hierarchy, so let's put all of the contents of $dirlink (actually,
662 # the contents of $target) into @ARGV; as a side effect down the
663 # line, $dirlink will get created as an _actual_ directory.
664 expand_glob($dirlink);
666 if (-l "$Dest_dir/$dirlink") {
667 unlink "$Dest_dir/$dirlink" or
668 print STDERR "Could not remove link $Dest_dir/$dirlink: $!\n";
671 if (eval 'symlink($target, "$Dest_dir/$dirlink")') {
672 print "Linking $target -> $Dest_dir/$dirlink\n";
674 # Make sure that the link _links_ to something:
675 if (! -e "$Dest_dir/$target") {
676 mkpath("$Dest_dir/$target", 0755) or
677 print STDERR "Could not create $Dest_dir/$target/\n";
680 print STDERR "Could not symlink $target -> $Dest_dir/$dirlink: $!\n";
686 # Push all #included files in $file onto our stack, except for STDIN
687 # and files we've already processed.
688 sub queue_includes_from
693 return if ($file eq "-");
695 open HEADER, $file or return;
696 while (defined($line = <HEADER>)) {
697 while (/\\$/) { # Handle continuation lines
702 if ($line =~ /^#\s*include\s+<(.*?)>/) {
703 push(@ARGV, $1) unless $Is_converted{$1};
710 # Determine include directories; $Config{usrinc} should be enough for (all
711 # non-GCC?) C compilers, but gcc uses an additional include directory.
714 my $from_gcc = `$Config{cc} -v 2>&1`;
715 $from_gcc =~ s:^Reading specs from (.*?)/specs\b.*:$1/include:s;
717 length($from_gcc) ? ($from_gcc, $Config{usrinc}) : ($Config{usrinc});
721 # Create "_h2ph_pre.ph", if it doesn't exist or was built by a different
723 sub build_preamble_if_necessary
725 # Increment $VERSION every time this function is modified:
727 my $preamble = "$Dest_dir/_h2ph_pre.ph";
729 # Can we skip building the preamble file?
731 # Extract version number from first line of preamble:
732 open PREAMBLE, $preamble or die "Cannot open $preamble: $!";
733 my $line = <PREAMBLE>;
734 $line =~ /(\b\d+\b)/;
735 close PREAMBLE or die "Cannot close $preamble: $!";
737 # Don't build preamble if a compatible preamble exists:
738 return if $1 == $VERSION;
741 my (%define) = _extract_cc_defines();
743 open PREAMBLE, ">$preamble" or die "Cannot open $preamble: $!";
744 print PREAMBLE "# This file was created by h2ph version $VERSION\n";
746 foreach (sort keys %define) {
748 print PREAMBLE "# $_=$define{$_}\n";
751 if ($define{$_} =~ /^(\d+)U?L{0,2}$/i) {
753 "unless (defined &$_) { sub $_() { $1 } }\n\n";
754 } elsif ($define{$_} =~ /^\w+$/) {
756 "unless (defined &$_) { sub $_() { &$define{$_} } }\n\n";
759 "unless (defined &$_) { sub $_() { \"",
760 quotemeta($define{$_}), "\" } }\n\n";
763 close PREAMBLE or die "Cannot close $preamble: $!";
767 # %Config contains information on macros that are pre-defined by the
768 # system's compiler. We need this information to make the .ph files
769 # function with perl as the .h files do with cc.
770 sub _extract_cc_defines
773 my $allsymbols = join " ",
774 @Config{'ccsymbols', 'cppsymbols', 'cppccsymbols'};
776 # Split compiler pre-definitions into `key=value' pairs:
777 foreach (split /\s+/, $allsymbols) {
778 /(.+?)=(.+)/ and $define{$1} = $2;
781 print STDERR "$_: $1 -> $2\n";
791 ##############################################################################
796 h2ph - convert .h C header files to .ph Perl header files
800 B<h2ph [-d destination directory] [-r | -a] [-l] [headerfiles]>
805 converts any C header files specified to the corresponding Perl header file
807 It is most easily run while in /usr/include:
809 cd /usr/include; h2ph * sys/*
813 cd /usr/include; h2ph * sys/* arpa/* netinet/*
817 cd /usr/include; h2ph -r -l .
819 The output files are placed in the hierarchy rooted at Perl's
820 architecture dependent library directory. You can specify a different
821 hierarchy with a B<-d> switch.
823 If run with no arguments, filters standard input to standard output.
829 =item -d destination_dir
831 Put the resulting B<.ph> files beneath B<destination_dir>, instead of
832 beneath the default Perl library location (C<$Config{'installsitsearch'}>).
836 Run recursively; if any of B<headerfiles> are directories, then run I<h2ph>
837 on all files in those directories (and their subdirectories, etc.). B<-r>
838 and B<-a> are mutually exclusive.
842 Run automagically; convert B<headerfiles>, as well as any B<.h> files
843 which they include. This option will search for B<.h> files in all
844 directories which your C compiler ordinarily uses. B<-a> and B<-r> are
849 Symbolic links will be replicated in the destination directory. If B<-l>
850 is not specified, then links are skipped over.
854 Put ``hints'' in the .ph files which will help in locating problems with
855 I<h2ph>. In those cases when you B<require> a B<.ph> file containing syntax
856 errors, instead of the cryptic
858 [ some error condition ] at (eval mmm) line nnn
860 you will see the slightly more helpful
862 [ some error condition ] at filename.ph line nnn
864 However, the B<.ph> files almost double in size when built using B<-h>.
868 Include the code from the B<.h> file as a comment in the B<.ph> file.
869 This is primarily used for debugging I<h2ph>.
873 ``Quiet'' mode; don't print out the names of the files being converted.
879 No environment variables are used.
898 The usual warnings if it can't read or write the files involved.
902 Doesn't construct the %sizeof array for you.
904 It doesn't handle all C constructs, but it does attempt to isolate
905 definitions inside evals so that you can get at the definitions
906 that it can translate.
908 It's only intended as a rough tool.
909 You may need to dicker with the files produced.
911 You have to run this program by hand; it's not run as part of the Perl
914 Doesn't handle complicated expressions built piecemeal, a la:
924 Doesn't necessarily locate all of your C compiler's internally-defined
931 close OUT or die "Can't close $file: $!";
932 chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
933 exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';