This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl.h: Add comments
[perl5.git] / utils / h2ph.PL
1 #!/usr/local/bin/perl
2
3 use strict;
4 use warnings;
5
6 use Config;
7 use File::Basename qw(basename dirname);
8 use Cwd;
9
10 # List explicitly here the variables you want Configure to
11 # generate.  Metaconfig only looks for shell variables, so you
12 # have to mention them as if they were shell variables, not
13 # %Config entries.  Thus you write
14 #  $startperl
15 # to ensure Configure will look for $Config{startperl}.
16 # Wanted:  $archlibexp
17
18 # This forces PL files to create target in same directory as PL file.
19 # This is so that make depend always knows where to find PL derivatives.
20 my $origdir = cwd;
21 chdir dirname($0);
22 my $file = basename($0, '.PL');
23 $file .= '.com' if $^O eq 'VMS';
24
25 open OUT, '>', $file or die "Can't create $file: $!";
26
27 print "Extracting $file (with variable substitutions)\n";
28
29 # In this section, perl variables will be expanded during extraction.
30 # You can use $Config{...} to use Configure variables.
31
32 print OUT <<"!GROK!THIS!";
33 $Config{startperl}
34     eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
35         if 0; # ^ Run only under a shell
36 !GROK!THIS!
37
38 # In the following, perl variables are not expanded during extraction.
39
40 print OUT <<'!NO!SUBS!';
41
42 BEGIN { pop @INC if $INC[-1] eq '.' }
43
44 use strict;
45
46 use Config;
47 use File::Path qw(mkpath);
48 use Getopt::Std;
49
50 # Make sure read permissions for all are set:
51 if (defined umask && (umask() & 0444)) {
52     umask (umask() & ~0444);
53 }
54
55 getopts('Dd:rlhaQe');
56 use vars qw($opt_D $opt_d $opt_r $opt_l $opt_h $opt_a $opt_Q $opt_e);
57 die "-r and -a options are mutually exclusive\n" if ($opt_r and $opt_a);
58 my @inc_dirs = inc_dirs() if $opt_a;
59
60 my $Exit = 0;
61
62 my $Dest_dir = $opt_d || $Config{installsitearch};
63 die "Destination directory $Dest_dir doesn't exist or isn't a directory\n"
64     unless -d $Dest_dir;
65
66 my @isatype = qw(
67         char    uchar   u_char
68         short   ushort  u_short
69         int     uint    u_int
70         long    ulong   u_long
71         FILE    key_t   caddr_t
72         float   double  size_t
73 );
74
75 my %isatype;
76 @isatype{@isatype} = (1) x @isatype;
77 my $inif = 0;
78 my %Is_converted;
79 my %bad_file = ();
80
81 @ARGV = ('-') unless @ARGV;
82
83 build_preamble_if_necessary();
84
85 sub reindent($) {
86     my($text) = shift;
87     $text =~ s/\n/\n    /g;
88     $text =~ s/        /\t/g;
89     $text;
90 }
91
92 my ($t, $tab, %curargs, $new, $eval_index, $dir, $name, $args, $outfile);
93 my ($incl, $incl_type, $incl_quote, $next);
94 while (defined (my $file = next_file())) {
95     if (-l $file and -d $file) {
96         link_if_possible($file) if ($opt_l);
97         next;
98     }
99
100     # Recover from header files with unbalanced cpp directives
101     $t = '';
102     $tab = 0;
103
104     # $eval_index goes into '#line' directives, to help locate syntax errors:
105     $eval_index = 1;
106
107     if ($file eq '-') {
108         open(IN, "-");
109         open(OUT, ">-");
110     } else {
111         ($outfile = $file) =~ s/\.h$/.ph/ || next;
112         print "$file -> $outfile\n" unless $opt_Q;
113         if ($file =~ m|^(.*)/|) {
114             $dir = $1;
115             mkpath "$Dest_dir/$dir";
116         }
117
118         if ($opt_a) { # automagic mode:  locate header file in @inc_dirs
119             foreach (@inc_dirs) {
120                 chdir $_;
121                 last if -f $file;
122             }
123         }
124
125         open(IN, "<", "$file") || (($Exit = 1),(warn "Can't open $file: $!\n"),next);
126         open(OUT, ">", "$Dest_dir/$outfile") || die "Can't create $outfile: $!\n";
127     }
128
129     print OUT
130         "require '_h2ph_pre.ph';\n\n",
131         "no warnings qw(redefine misc);\n\n";
132
133     while (defined (local $_ = next_line($file))) {
134         if (s/^\s*\#\s*//) {
135             if (s/^define\s+(\w+)//) {
136                 $name = $1;
137                 $new = '';
138                 s/\s+$//;
139                 s/\(\w+\s*\(\*\)\s*\(\w*\)\)\s*(-?\d+)/$1/; # (int (*)(foo_t))0
140                 if (s/^\(([\w,\s]*)\)//) {
141                     $args = $1;
142                     my $proto = '() ';
143                     if ($args ne '') {
144                         $proto = '';
145                         foreach my $arg (split(/,\s*/,$args)) {
146                             $arg =~ s/^\s*([^\s].*[^\s])\s*$/$1/;
147                             $curargs{$arg} = 1;
148                         }
149                         $args =~ s/\b(\w)/\$$1/g;
150                         $args = "my($args) = \@_;\n$t    ";
151                     }
152                     s/^\s+//;
153                     expr();
154                     $new =~ s/(["\\])/\\$1/g;       #"]);
155                     EMIT($proto);
156                 } else {
157                     s/^\s+//;
158                     expr();
159
160                     $new = 1 if $new eq '';
161
162                     # Shunt around such directives as '#define FOO FOO':
163                     next if $new =~ /^\s*&\Q$name\E\s*\z/;
164
165                     $new = reindent($new);
166                     $args = reindent($args);
167                     $new =~ s/(['\\])/\\$1/g;        #']);
168
169                     print OUT $t, 'eval ';
170                     if ($opt_h) {
171                         print OUT "\"\\n#line $eval_index $outfile\\n\" . ";
172                         $eval_index++;
173                     }
174                     print OUT "'sub $name () {$new;}' unless defined(&$name);\n";
175                 }
176             } elsif (/^(include|import|include_next)\s*([<\"])(.*)[>\"]/) {
177                 $incl_type = $1;
178                 $incl_quote = $2;
179                 $incl = $3;
180                 if (($incl_type eq 'include_next') ||
181                     ($opt_e && exists($bad_file{$incl}))) {
182                     $incl =~ s/\.h$/.ph/;
183                 print OUT ($t,
184                            "eval {\n");
185                 $tab += 4;
186                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
187                     print OUT ($t, "my(\@REM);\n");
188                     if ($incl_type eq 'include_next') {
189                 print OUT ($t,
190                            "my(\%INCD) = map { \$INC{\$_} => 1 } ",
191                                    "(grep { \$_ eq \"$incl\" } ",
192                                    "keys(\%INC));\n");
193                 print OUT ($t,
194                                    "\@REM = map { \"\$_/$incl\" } ",
195                            "(grep { not exists(\$INCD{\"\$_/$incl\"})",
196                                    " and -f \"\$_/$incl\" } \@INC);\n");
197                     } else {
198                         print OUT ($t,
199                                    "\@REM = map { \"\$_/$incl\" } ",
200                                    "(grep {-r \"\$_/$incl\" } \@INC);\n");
201                     }
202                 print OUT ($t,
203                            "require \"\$REM[0]\" if \@REM;\n");
204                 $tab -= 4;
205                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
206                 print OUT ($t,
207                            "};\n");
208                 print OUT ($t,
209                            "warn(\$\@) if \$\@;\n");
210                 } else {
211                     $incl =~ s/\.h$/.ph/;
212                     # copy the prefix in the quote syntax (#include "x.h") case
213                     if ($incl !~ m|/| && $incl_quote eq q{"} && $file =~ m|^(.*)/|) {
214                         $incl = "$1/$incl";
215                     }
216                     print OUT $t,"require '$incl';\n";
217                 }
218             } elsif (/^ifdef\s+(\w+)/) {
219                 print OUT $t,"if(defined(&$1)) {\n";
220                 $tab += 4;
221                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
222             } elsif (/^ifndef\s+(\w+)/) {
223                 print OUT $t,"unless(defined(&$1)) {\n";
224                 $tab += 4;
225                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
226             } elsif (s/^if\s+//) {
227                 $new = '';
228                 $inif = 1;
229                 expr();
230                 $inif = 0;
231                 print OUT $t,"if($new) {\n";
232                 $tab += 4;
233                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
234             } elsif (s/^elif\s+//) {
235                 $new = '';
236                 $inif = 1;
237                 expr();
238                 $inif = 0;
239                 $tab -= 4;
240                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
241                 print OUT $t,"}\n elsif($new) {\n";
242                 $tab += 4;
243                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
244             } elsif (/^else/) {
245                 $tab -= 4;
246                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
247                 print OUT $t,"} else {\n";
248                 $tab += 4;
249                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
250             } elsif (/^endif/) {
251                 $tab -= 4;
252                 $t = "\t" x ($tab / 8) . ' ' x ($tab % 8);
253                 print OUT $t,"}\n";
254             } elsif(/^undef\s+(\w+)/) {
255                 print OUT $t, "undef(&$1) if defined(&$1);\n";
256             } elsif(/^error\s+(".*")/) {
257                 print OUT $t, "die($1);\n";
258             } elsif(/^error\s+(.*)/) {
259                 print OUT $t, "die(\"", quotemeta($1), "\");\n";
260             } elsif(/^warning\s+(.*)/) {
261                 print OUT $t, "warn(\"", quotemeta($1), "\");\n";
262             } elsif(/^ident\s+(.*)/) {
263                 print OUT $t, "# $1\n";
264             }
265         } elsif (/^\s*(typedef\s*)?enum\s*(\s+[a-zA-Z_]\w*\s*)?/) { # { for vi
266             until(/\{[^}]*\}.*;/ || /;/) {
267                 last unless defined ($next = next_line($file));
268                 chomp $next;
269                 # drop "#define FOO FOO" in enums
270                 $next =~ s/^\s*#\s*define\s+(\w+)\s+\1\s*$//;
271                 # #defines in enums (aliases)
272                 $next =~ s/^\s*#\s*define\s+(\w+)\s+(\w+)\s*$/$1 = $2,/;
273                 $_ .= $next;
274                 print OUT "# $next\n" if $opt_D;
275             }
276             s/#\s*if.*?#\s*endif//g; # drop #ifdefs
277             s@/\*.*?\*/@@g;
278             s/\s+/ /g;
279             next unless /^\s?(typedef\s?)?enum\s?([a-zA-Z_]\w*)?\s?\{(.*)\}\s?([a-zA-Z_]\w*)?\s?;/;
280             (my $enum_subs = $3) =~ s/\s//g;
281             my @enum_subs = split(/,/, $enum_subs);
282             my $enum_val = -1;
283             foreach my $enum (@enum_subs) {
284                 my ($enum_name, $enum_value) = $enum =~ /^([a-zA-Z_]\w*)(=.+)?$/;
285                 $enum_name or next;
286                 $enum_value =~ s/^=//;
287                 $enum_val = (length($enum_value) ? $enum_value : $enum_val + 1);
288                 if ($opt_h) {
289                     print OUT ($t,
290                                "eval(\"\\n#line $eval_index $outfile\\n",
291                                "sub $enum_name () \{ $enum_val; \}\") ",
292                                "unless defined(\&$enum_name);\n");
293                     ++ $eval_index;
294                 } else {
295                     print OUT ($t,
296                                "eval(\"sub $enum_name () \{ $enum_val; \}\") ",
297                                "unless defined(\&$enum_name);\n");
298                 }
299             }
300         } elsif (/^(?:__extension__\s+)?(?:extern|static)\s+(?:__)?inline(?:__)?\s+/
301             and !/;\s*$/ and !/{\s*}\s*$/)
302         { # { for vi
303             # This is a hack to parse the inline functions in the glibc headers.
304             # Warning: massive kludge ahead. We suppose inline functions
305             # are mainly constructed like macros.
306             while (1) {
307                 last unless defined ($next = next_line($file));
308                 chomp $next;
309                 undef $_, last if $next =~ /__THROW\s*;/
310                                or $next =~ /^(__extension__|extern|static)\b/;
311                 $_ .= " $next";
312                 print OUT "# $next\n" if $opt_D;
313                 last if $next =~ /^}|^{.*}\s*$/;
314             }
315             next if not defined; # because it's only a prototype
316             s/\b(__extension__|extern|static|(?:__)?inline(?:__)?)\b//g;
317             # violently drop #ifdefs
318             s/#\s*if.*?#\s*endif//g
319                 and print OUT "# some #ifdef were dropped here -- fill in the blanks\n";
320             if (s/^(?:\w|\s|\*)*\s(\w+)\s*//) {
321                 $name = $1;
322             } else {
323                 warn "name not found"; next; # shouldn't occur...
324             }
325             my @args;
326             if (s/^\(([^()]*)\)\s*(\w+\s*)*//) {
327                 for my $arg (split /,/, $1) {
328                     if ($arg =~ /(\w+)\s*$/) {
329                         $curargs{$1} = 1;
330                         push @args, $1;
331                     }
332                 }
333             }
334             $args = (
335                 @args
336                 ? "my(" . (join ',', map "\$$_", @args) . ") = \@_;\n$t    "
337                 : ""
338             );
339             my $proto = @args ? '' : '() ';
340             $new = '';
341             s/\breturn\b//g; # "return" doesn't occur in macros usually...
342             expr();
343             # try to find and perlify local C variables
344             our @local_variables = (); # needs to be a our(): (?{...}) bug workaround
345             {
346                 use re "eval";
347                 my $typelist = join '|', keys %isatype;
348                 $new =~ s['
349                   (?:(?:__)?const(?:__)?\s+)?
350                   (?:(?:un)?signed\s+)?
351                   (?:long\s+)?
352                   (?:$typelist)\s+
353                   (\w+)
354                   (?{ push @local_variables, $1 })
355                   ']
356                  [my \$$1]gx;
357                 $new =~ s['
358                   (?:(?:__)?const(?:__)?\s+)?
359                   (?:(?:un)?signed\s+)?
360                   (?:long\s+)?
361                   (?:$typelist)\s+
362                   ' \s+ &(\w+) \s* ;
363                   (?{ push @local_variables, $1 })
364                   ]
365                  [my \$$1;]gx;
366              }
367             $new =~ s/&$_\b/\$$_/g for @local_variables;
368             $new =~ s/(["\\])/\\$1/g;       #"]);
369             # now that's almost like a macro (we hope)
370             EMIT($proto);
371         }
372     }
373     $Is_converted{$file} = 1;
374     if ($opt_e && exists($bad_file{$file})) {
375         unlink($Dest_dir . '/' . $outfile);
376         $next = '';
377     } else {
378         print OUT "1;\n";
379         queue_includes_from($file) if $opt_a;
380     }
381 }
382
383 if ($opt_e && (scalar(keys %bad_file) > 0)) {
384     warn "Was unable to convert the following files:\n";
385     warn "\t" . join("\n\t",sort(keys %bad_file)) . "\n";
386 }
387
388 exit $Exit;
389
390 sub EMIT {
391     my $proto = shift;
392
393     $new = reindent($new);
394     $args = reindent($args);
395     if ($t ne '') {
396     $new =~ s/(['\\])/\\$1/g;   #']);
397     if ($opt_h) {
398         print OUT $t,
399                     "eval \"\\n#line $eval_index $outfile\\n\" . 'sub $name $proto\{\n$t    ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
400                     $eval_index++;
401     } else {
402         print OUT $t,
403                     "eval 'sub $name $proto\{\n$t    ${args}eval q($new);\n$t}' unless defined(\&$name);\n";
404     }
405     } else {
406               print OUT "unless(defined(\&$name)) {\n    sub $name $proto\{\n\t${args}eval q($new);\n    }\n}\n";
407     }
408     %curargs = ();
409     return;
410 }
411
412 sub expr {
413     if (/\b__asm__\b/) {        # freak out
414         $new = '"(assembly code)"';
415         return
416     }
417     my $joined_args;
418     if(keys(%curargs)) {
419         $joined_args = join('|', keys(%curargs));
420     }
421     while ($_ ne '') {
422         s/^\&\&// && do { $new .= " &&"; next;}; # handle && operator
423         s/^\&([\(a-z\)]+)/$1/i; # hack for things that take the address of
424         s/^(\s+)//              && do {$new .= ' '; next;};
425         s/^0X([0-9A-F]+)[UL]*//i
426             && do {my $hex = $1;
427                    $hex =~ s/^0+//;
428                    if (length $hex > 8 && !$Config{use64bitint}) {
429                        # Croak if nv_preserves_uv_bits < 64 ?
430                        $new .=         hex(substr($hex, -8)) +
431                                2**32 * hex(substr($hex,  0, -8));
432                        # The above will produce "erroneous" code
433                        # if the hex constant was e.g. inside UINT64_C
434                        # macro, but then again, h2ph is an approximation.
435                    } else {
436                        $new .= lc("0x$hex");
437                    }
438                    next;};
439         s/^(-?\d+\.\d+E[-+]?\d+)[FL]?//i        && do {$new .= $1; next;};
440         s/^(\d+)\s*[LU]*//i     && do {$new .= $1; next;};
441         s/^("(\\"|[^"])*")//    && do {$new .= $1; next;};
442         s/^'((\\"|[^"])*)'//    && do {
443             if ($curargs{$1}) {
444                 $new .= "ord('\$$1')";
445             } else {
446                 $new .= "ord('$1')";
447             }
448             next;
449         };
450         # replace "sizeof(foo)" with "{foo}"
451         # also, remove * (C dereference operator) to avoid perl syntax
452         # problems.  Where the %sizeof array comes from is anyone's
453         # guess (c2ph?), but this at least avoids fatal syntax errors.
454         # Behavior is undefined if sizeof() delimiters are unbalanced.
455         # This code was modified to able to handle constructs like this:
456         #   sizeof(*(p)), which appear in the HP-UX 10.01 header files.
457         s/^sizeof\s*\(// && do {
458             $new .= '$sizeof';
459             my $lvl = 1;  # already saw one open paren
460             # tack { on the front, and skip it in the loop
461             $_ = "{" . "$_";
462             my $index = 1;
463             # find balanced closing paren
464             while ($index <= length($_) && $lvl > 0) {
465                 $lvl++ if substr($_, $index, 1) eq "(";
466                 $lvl-- if substr($_, $index, 1) eq ")";
467                 $index++;
468             }
469             # tack } on the end, replacing )
470             substr($_, $index - 1, 1) = "}";
471             # remove pesky * operators within the sizeof argument
472             substr($_, 0, $index - 1) =~ s/\*//g;
473             next;
474         };
475         # Eliminate typedefs
476         /\(([\w\s]+)[\*\s]*\)\s*[\w\(]/ && do {
477             my $doit = 1;
478             foreach (split /\s+/, $1) {  # Make sure all the words are types,
479                 unless($isatype{$_} or $_ eq 'struct' or $_ eq 'union'){
480                     $doit = 0;
481                     last;
482                 }
483             }
484             if( $doit ){
485                 s/\([\w\s]+[\*\s]*\)// && next;      # then eliminate them.
486             }
487         };
488         # struct/union member, including arrays:
489         s/^([_A-Z]\w*(\[[^\]]+\])?((\.|->)[_A-Z]\w*(\[[^\]]+\])?)+)//i && do {
490             my $id = $1;
491             $id =~ s/(\.|(->))([^\.\-]*)/->\{$3\}/g;
492             $id =~ s/\b([^\$])($joined_args)/$1\$$2/g if length($joined_args);
493             while($id =~ /\[\s*([^\$\&\d\]]+)\]/) {
494                 my($index) = $1;
495                 $index =~ s/\s//g;
496                 if(exists($curargs{$index})) {
497                     $index = "\$$index";
498                 } else {
499                     $index = "&$index";
500                 }
501                 $id =~ s/\[\s*([^\$\&\d\]]+)\]/[$index]/;
502             }
503             $new .= " (\$$id)";
504         };
505         s/^([_a-zA-Z]\w*)//     && do {
506             my $id = $1;
507             if ($id eq 'struct' || $id eq 'union') {
508                 s/^\s+(\w+)//;
509                 $id .= ' ' . $1;
510                 $isatype{$id} = 1;
511             } elsif ($id =~ /^((un)?signed)|(long)|(short)$/) {
512                 while (s/^\s+(\w+)//) { $id .= ' ' . $1; }
513                 $isatype{$id} = 1;
514             }
515             if ($curargs{$id}) {
516                 $new .= "\$$id";
517                 $new .= '->' if /^[\[\{]/;
518             } elsif ($id eq 'defined') {
519                 $new .= 'defined';
520             } elsif (/^\s*\(/) {
521                 s/^\s*\((\w),/("$1",/ if $id =~ /^_IO[WR]*$/i;  # cheat
522                 $new .= " &$id";
523             } elsif ($isatype{$id}) {
524                 if ($new =~ /\{\s*$/) {
525                     $new .= "'$id'";
526                 } elsif ($new =~ /\(\s*$/ && /^[\s*]*\)/) {
527                     $new =~ s/\(\s*$//;
528                     s/^[\s*]*\)//;
529                 } else {
530                     $new .= q(').$id.q(');
531                 }
532             } else {
533                 if ($inif) {
534                     if ($new =~ /defined\s*$/) {
535                         $new .= '(&' . $id . ')';
536                     } elsif ($new =~ /defined\s*\($/) {
537                         $new .= '&' . $id;
538                     } else {
539                         $new .= '(defined(&' . $id . ') ? &' . $id . ' : undef)';
540                     }
541                 } elsif (/^\[/) {
542                     $new .= " \$$id";
543                 } else {
544                     $new .= ' &' . $id;
545                 }
546             }
547             next;
548         };
549         s/^(.)// && do { if ($1 ne '#') { $new .= $1; } next;};
550     }
551 }
552
553
554 sub next_line
555 {
556     my $file = shift;
557     my ($in, $out);
558     my $pre_sub_tri_graphs = 1;
559
560     READ: while (not eof IN) {
561         $in  .= <IN>;
562         chomp $in;
563         next unless length $in;
564
565         while (length $in) {
566             if ($pre_sub_tri_graphs) {
567                 # Preprocess all tri-graphs
568                 # including things stuck in quoted string constants.
569                 $in =~ s/\?\?=/#/g;                         # | ??=|  #|
570                 $in =~ s/\?\?\!/|/g;                        # | ??!|  ||
571                 $in =~ s/\?\?'/^/g;                         # | ??'|  ^|
572                 $in =~ s/\?\?\(/[/g;                        # | ??(|  [|
573                 $in =~ s/\?\?\)/]/g;                        # | ??)|  ]|
574                 $in =~ s/\?\?\-/~/g;                        # | ??-|  ~|
575                 $in =~ s/\?\?\//\\/g;                       # | ??/|  \|
576                 $in =~ s/\?\?</{/g;                         # | ??<|  {|
577                 $in =~ s/\?\?>/}/g;                         # | ??>|  }|
578             }
579             if ($in =~ /^\#ifdef __LANGUAGE_PASCAL__/) {
580                 # Tru64 disassembler.h evilness: mixed C and Pascal.
581                 while (<IN>) {
582                     last if /^\#endif/;
583                 }
584                 $in = "";
585                 next READ;
586             }
587             if ($in =~ /^extern inline / && # Inlined assembler.
588                 $^O eq 'linux' && $file =~ m!(?:^|/)asm/[^/]+\.h$!) {
589                 while (<IN>) {
590                     last if /^}/;
591                 }
592                 $in = "";
593                 next READ;
594             }
595             if ($in =~ s/\\$//) {                           # \-newline
596                 $out    .= ' ';
597                 next READ;
598             } elsif ($in =~ s/^([^"'\\\/]+)//) {            # Passthrough
599                 $out    .= $1;
600             } elsif ($in =~ s/^(\\.)//) {                   # \...
601                 $out    .= $1;
602             } elsif ($in =~ /^'/) {                         # '...
603                 if ($in =~ s/^('(\\.|[^'\\])*')//) {
604                     $out    .= $1;
605                 } else {
606                     next READ;
607                 }
608             } elsif ($in =~ /^"/) {                         # "...
609                 if ($in =~ s/^("(\\.|[^"\\])*")//) {
610                     $out    .= $1;
611                 } else {
612                     next READ;
613                 }
614             } elsif ($in =~ s/^\/\/.*//) {                  # //...
615                 # fall through
616             } elsif ($in =~ m/^\/\*/) {                     # /*...
617                 # C comment removal adapted from perlfaq6:
618                 if ($in =~ s/^\/\*[^*]*\*+([^\/*][^*]*\*+)*\///) {
619                     $out    .= ' ';
620                 } else {                                    # Incomplete /* */
621                     next READ;
622                 }
623             } elsif ($in =~ s/^(\/)//) {                    # /...
624                 $out    .= $1;
625             } elsif ($in =~ s/^([^\'\"\\\/]+)//) {
626                 $out    .= $1;
627             } elsif ($^O eq 'linux' &&
628                      $file =~ m!(?:^|/)linux/byteorder/pdp_endian\.h$! &&
629                      $in   =~ s!\'T KNOW!!) {
630                 $out    =~ s!I DON$!I_DO_NOT_KNOW!;
631             } else {
632                 if ($opt_e) {
633                     warn "Cannot parse $file:\n$in\n";
634                     $bad_file{$file} = 1;
635                     $in = '';
636                     $out = undef;
637                     last READ;
638                 } else {
639                 die "Cannot parse:\n$in\n";
640                 }
641             }
642         }
643
644         last READ if $out =~ /\S/;
645     }
646
647     return $out;
648 }
649
650
651 # Handle recursive subdirectories without getting a grotesquely big stack.
652 # Could this be implemented using File::Find?
653 sub next_file
654 {
655     my $file;
656
657     while (@ARGV) {
658         $file = shift @ARGV;
659
660         if ($file eq '-' or -f $file or -l $file) {
661             return $file;
662         } elsif (-d $file) {
663             if ($opt_r) {
664                 expand_glob($file);
665             } else {
666                 print STDERR "Skipping directory '$file'\n";
667             }
668         } elsif ($opt_a) {
669             return $file;
670         } else {
671             print STDERR "Skipping '$file':  not a file or directory\n";
672         }
673     }
674
675     return undef;
676 }
677
678
679 # Put all the files in $directory into @ARGV for processing.
680 sub expand_glob
681 {
682     my ($directory)  = @_;
683
684     $directory =~ s:/$::;
685
686     opendir DIR, $directory;
687         foreach (readdir DIR) {
688             next if ($_ eq '.' or $_ eq '..');
689
690             # expand_glob() is going to be called until $ARGV[0] isn't a
691             # directory; so push directories, and unshift everything else.
692             if (-d "$directory/$_") { push    @ARGV, "$directory/$_" }
693             else                    { unshift @ARGV, "$directory/$_" }
694         }
695     closedir DIR;
696 }
697
698
699 # Given $file, a symbolic link to a directory in the C include directory,
700 # make an equivalent symbolic link in $Dest_dir, if we can figure out how.
701 # Otherwise, just duplicate the file or directory.
702 sub link_if_possible
703 {
704     my ($dirlink)  = @_;
705     my $target  = eval 'readlink($dirlink)';
706
707     if ($target =~ m:^\.\./: or $target =~ m:^/:) {
708         # The target of a parent or absolute link could leave the $Dest_dir
709         # hierarchy, so let's put all of the contents of $dirlink (actually,
710         # the contents of $target) into @ARGV; as a side effect down the
711         # line, $dirlink will get created as an _actual_ directory.
712         expand_glob($dirlink);
713     } else {
714         if (-l "$Dest_dir/$dirlink") {
715             unlink "$Dest_dir/$dirlink" or
716                 print STDERR "Could not remove link $Dest_dir/$dirlink:  $!\n";
717         }
718
719         if (eval 'symlink($target, "$Dest_dir/$dirlink")') {
720             print "Linking $target -> $Dest_dir/$dirlink\n";
721
722             # Make sure that the link _links_ to something:
723             if (! -e "$Dest_dir/$target") {
724                 mkpath("$Dest_dir/$target", 0755) or
725                     print STDERR "Could not create $Dest_dir/$target/\n";
726             }
727         } else {
728             print STDERR "Could not symlink $target -> $Dest_dir/$dirlink:  $!\n";
729         }
730     }
731 }
732
733
734 # Push all #included files in $file onto our stack, except for STDIN
735 # and files we've already processed.
736 sub queue_includes_from
737 {
738     my ($file)    = @_;
739     my $line;
740
741     return if ($file eq "-");
742
743     open HEADER, "<", $file or return;
744         while (defined($line = <HEADER>)) {
745             while (/\\$/) { # Handle continuation lines
746                 chop $line;
747                 $line .= <HEADER>;
748             }
749
750             if ($line =~ /^#\s*include\s+([<"])(.*?)[>"]/) {
751                 my ($delimiter, $new_file) = ($1, $2);
752                 # copy the prefix in the quote syntax (#include "x.h") case
753                 if ($delimiter eq q{"} && $file =~ m|^(.*)/|) {
754                     $new_file = "$1/$new_file";
755                 }
756                 push(@ARGV, $new_file) unless $Is_converted{$new_file};
757             }
758         }
759     close HEADER;
760 }
761
762
763 # Determine include directories; $Config{usrinc} should be enough for (all
764 # non-GCC?) C compilers, but gcc uses additional include directories.
765 sub inc_dirs
766 {
767     my $from_gcc   = `LC_ALL=C $Config{cc} -v -E - < /dev/null 2>&1 | awk '/^#include/, /^End of search list/' | grep '^ '`;
768     length($from_gcc) ? (split(' ', $from_gcc), $Config{usrinc}) : ($Config{usrinc});
769 }
770
771
772 # Create "_h2ph_pre.ph", if it doesn't exist or was built by a different
773 # version of h2ph.
774 sub build_preamble_if_necessary
775 {
776     # Increment $VERSION every time this function is modified:
777     my $VERSION     = 4;
778     my $preamble    = "$Dest_dir/_h2ph_pre.ph";
779
780     # Can we skip building the preamble file?
781     if (-r $preamble) {
782         # Extract version number from first line of preamble:
783         open  PREAMBLE, "<", $preamble or die "Cannot open $preamble:  $!";
784             my $line = <PREAMBLE>;
785             $line =~ /(\b\d+\b)/;
786         close PREAMBLE            or die "Cannot close $preamble:  $!";
787
788         # Don't build preamble if a compatible preamble exists:
789         return if $1 == $VERSION;
790     }
791
792     my (%define) = _extract_cc_defines();
793
794     open  PREAMBLE, ">", $preamble or die "Cannot open $preamble:  $!";
795         print PREAMBLE "# This file was created by h2ph version $VERSION\n";
796         # Prevent non-portable hex constants from warning.
797         #
798         # We still produce an overflow warning if we can't represent
799         # a hex constant as an integer.
800         print PREAMBLE "no warnings qw(portable);\n";
801
802         foreach (sort keys %define) {
803             if ($opt_D) {
804                 print PREAMBLE "# $_=$define{$_}\n";
805             }
806             if ($define{$_} =~ /^\((.*)\)$/) {
807                 # parenthesized value:  d=(v)
808                 $define{$_} = $1;
809             }
810             if (/^(\w+)\((\w)\)$/) {
811                 my($macro, $arg) = ($1, $2);
812                 my $def = $define{$_};
813                 $def =~ s/$arg/\$\{$arg\}/g;
814                 print PREAMBLE <<DEFINE;
815 unless (defined &$macro) { sub $macro(\$) { my (\$$arg) = \@_; \"$def\" } }
816
817 DEFINE
818             } elsif
819                 ($define{$_} =~ /^([+-]?(\d+)?\.\d+([eE][+-]?\d+)?)[FL]?$/) {
820                 # float:
821                 print PREAMBLE
822                     "unless (defined &$_) { sub $_() { $1 } }\n\n";
823             } elsif ($define{$_} =~ /^([+-]?\d+)U?L{0,2}$/i) {
824                 # integer:
825                 print PREAMBLE
826                     "unless (defined &$_) { sub $_() { $1 } }\n\n";
827             } elsif ($define{$_} =~ /^([+-]?0x[\da-f]+)U?L{0,2}$/i) {
828                 # hex integer
829                 # Special cased, since perl warns on hex integers
830                 # that can't be represented in a UV.
831                 #
832                 # This way we get the warning at time of use, so the user
833                 # only gets the warning if they happen to use this
834                 # platform-specific definition.
835                 my $code = $1;
836                 $code = "hex('$code')" if length $code > 10;
837                 print PREAMBLE
838                     "unless (defined &$_) { sub $_() { $code } }\n\n";
839             } elsif ($define{$_} =~ /^\w+$/) {
840                 my $def = $define{$_};
841                 if ($isatype{$def}) {
842                   print PREAMBLE
843                     "unless (defined &$_) { sub $_() { \"$def\" } }\n\n";
844                 } else {
845                   print PREAMBLE
846                     "unless (defined &$_) { sub $_() { &$def } }\n\n";
847                 }
848             } else {
849                 print PREAMBLE
850                     "unless (defined &$_) { sub $_() { \"",
851                     quotemeta($define{$_}), "\" } }\n\n";
852             }
853         }
854         print PREAMBLE "\n1;\n";  # avoid 'did not return a true value' when empty
855     close PREAMBLE               or die "Cannot close $preamble:  $!";
856 }
857
858
859 # %Config contains information on macros that are pre-defined by the
860 # system's compiler.  We need this information to make the .ph files
861 # function with perl as the .h files do with cc.
862 sub _extract_cc_defines
863 {
864     my %define;
865     my $allsymbols  = join " ",
866         @Config{'ccsymbols', 'cppsymbols', 'cppccsymbols'};
867
868     # Split compiler pre-definitions into 'key=value' pairs:
869     while ($allsymbols =~ /([^\s]+)=((\\\s|[^\s])+)/g) {
870         $define{$1} = $2;
871         if ($opt_D) {
872             print STDERR "$_:  $1 -> $2\n";
873         }
874     }
875
876     return %define;
877 }
878
879
880 1;
881
882 ##############################################################################
883 __END__
884
885 =head1 NAME
886
887 h2ph - convert .h C header files to .ph Perl header files
888
889 =head1 SYNOPSIS
890
891 B<h2ph [-d destination directory] [-r | -a] [-l] [-h] [-e] [-D] [-Q]
892 [headerfiles]>
893
894 =head1 DESCRIPTION
895
896 I<h2ph>
897 converts any C header files specified to the corresponding Perl header file
898 format.
899 It is most easily run while in /usr/include:
900
901         cd /usr/include; h2ph * sys/*
902
903 or
904
905         cd /usr/include; h2ph * sys/* arpa/* netinet/*
906
907 or
908
909         cd /usr/include; h2ph -r -l .
910
911 The output files are placed in the hierarchy rooted at Perl's
912 architecture dependent library directory.  You can specify a different
913 hierarchy with a B<-d> switch.
914
915 If run with no arguments, filters standard input to standard output.
916
917 =head1 OPTIONS
918
919 =over 4
920
921 =item -d destination_dir
922
923 Put the resulting B<.ph> files beneath B<destination_dir>, instead of
924 beneath the default Perl library location (C<$Config{'installsitearch'}>).
925
926 =item -r
927
928 Run recursively; if any of B<headerfiles> are directories, then run I<h2ph>
929 on all files in those directories (and their subdirectories, etc.).  B<-r>
930 and B<-a> are mutually exclusive.
931
932 =item -a
933
934 Run automagically; convert B<headerfiles>, as well as any B<.h> files
935 which they include.  This option will search for B<.h> files in all
936 directories which your C compiler ordinarily uses.  B<-a> and B<-r> are
937 mutually exclusive.
938
939 =item -l
940
941 Symbolic links will be replicated in the destination directory.  If B<-l>
942 is not specified, then links are skipped over.
943
944 =item -h
945
946 Put 'hints' in the .ph files which will help in locating problems with
947 I<h2ph>.  In those cases when you B<require> a B<.ph> file containing syntax
948 errors, instead of the cryptic
949
950         [ some error condition ] at (eval mmm) line nnn
951
952 you will see the slightly more helpful
953
954         [ some error condition ] at filename.ph line nnn
955
956 However, the B<.ph> files almost double in size when built using B<-h>.
957
958 =item -e
959
960 If an error is encountered during conversion, output file will be removed and
961 a warning emitted instead of terminating the conversion immediately.
962
963 =item -D
964
965 Include the code from the B<.h> file as a comment in the B<.ph> file.
966 This is primarily used for debugging I<h2ph>.
967
968 =item -Q
969
970 'Quiet' mode; don't print out the names of the files being converted.
971
972 =back
973
974 =head1 ENVIRONMENT
975
976 No environment variables are used.
977
978 =head1 FILES
979
980  /usr/include/*.h
981  /usr/include/sys/*.h
982
983 etc.
984
985 =head1 AUTHOR
986
987 Larry Wall
988
989 =head1 SEE ALSO
990
991 perl(1)
992
993 =head1 DIAGNOSTICS
994
995 The usual warnings if it can't read or write the files involved.
996
997 =head1 BUGS
998
999 Doesn't construct the %sizeof array for you.
1000
1001 It doesn't handle all C constructs, but it does attempt to isolate
1002 definitions inside evals so that you can get at the definitions
1003 that it can translate.
1004
1005 It's only intended as a rough tool.
1006 You may need to dicker with the files produced.
1007
1008 You have to run this program by hand; it's not run as part of the Perl
1009 installation.
1010
1011 Doesn't handle complicated expressions built piecemeal, a la:
1012
1013     enum {
1014         FIRST_VALUE,
1015         SECOND_VALUE,
1016     #ifdef ABC
1017         THIRD_VALUE
1018     #endif
1019     };
1020
1021 Doesn't necessarily locate all of your C compiler's internally-defined
1022 symbols.
1023
1024 =cut
1025
1026 !NO!SUBS!
1027
1028 close OUT or die "Can't close $file: $!";
1029 chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
1030 exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
1031 chdir $origdir;