]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/ansify/ansify.pl
MFV: zlib 1.3
[FreeBSD/FreeBSD.git] / tools / tools / ansify / ansify.pl
1 #!/usr/bin/perl -w
2 #-
3 # Copyright (c) 2005 Dag-Erling Smørgrav
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer
11 #    in this position and unchanged.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 #    notice, this list of conditions and the following disclaimer in the
14 #    documentation and/or other materials provided with the distribution.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 # SUCH DAMAGE.
27 #
28 #
29
30 use v5.6.0;
31 use strict;
32
33 use Getopt::Long;
34
35 my $caddr_t;
36
37 sub ansify($$$) {
38     my $ifh = shift;
39     my $ofh = shift;
40     my $fn = shift;
41
42     my $line = 0;
43   OUTER:
44     while (<$ifh>) {
45         # look for K&R-style function definitions
46         if (m/^(\w+)\s*\(([\w,\s]+)\)$/) {
47             my @saved = ($_);
48             my $func = $1;
49             my @args = split(/\s*,\s*/, $2);
50             my $arglist = "";
51             # capture K&R-style argument list
52             while (<$ifh>) {
53                 push(@saved, $_);
54                 last if (m/^\{\s*$/);
55                 $arglist .= $_;
56             }
57             # remove comments (common in vfs code)
58             $arglist =~ s/\/\*([^*]|\*[^\/])*\*\// /gs;
59             # identify type of each argument
60             my %type;
61             foreach (split('\n', $arglist)) {
62                 s/\s+/ /g;
63                 if (!/^\s*([\w\s\*]+?)\s*(\w+?);\s*$/) {
64                     warn("[$fn:$line] $func(): can't parse argument list\n");
65                     print $ofh @saved;
66                     $line += @saved;
67                     next OUTER;
68                 }
69                 $type{$2} = $1;
70             }
71             # construct ANSI-style function definition
72             my $repl = "$func(";
73             foreach my $arg (@args) {
74                 # missing arguments in argument list
75                 if (!exists($type{$arg})) {
76                     warn("[$fn:$line] $func(): unknown type for '$arg' argument\n");
77                     print $ofh @saved;
78                     $line += @saved;
79                     next OUTER;
80                 }
81                 if ($caddr_t) {
82                     $type{$arg} = "void *"
83                         if $type{$arg} eq "caddr_t";
84                 }
85                 $repl .= $type{$arg};
86                 $repl .= " "
87                     unless ($type{$arg} =~ m/\*$/);
88                 $repl .= $arg;
89                 $repl .= ", "
90                     unless $arg eq $args[-1];
91                 delete $type{$arg};
92             }
93             $repl .= ")";
94             # extra arguments in argument list
95             if (%type) {
96                 warn("[$fn:$line] $func(): too many arguments\n");
97                 print $ofh @saved;
98                 $line += @saved;
99                 next OUTER;
100             }
101             print $ofh "$repl\n";
102             ++$line;
103             # warn about long lines so they can be fixed up manually
104             warn("[$fn:$line] $func(): definition exceeds 80 characters\n")
105                 if length($repl) >= 80;
106             print $ofh "{\n";
107             ++$line;
108         } else {
109             print $ofh $_;
110             ++$line;
111         }
112     }
113 }
114
115 sub ansify_file($) {
116     my $fn = shift;
117
118     my $tfn = "$fn.ansify";
119     local *IN;
120     local *OUT;
121
122     if (open(IN, "<", $fn)) {
123         if (open(OUT, ">", $tfn)) {
124             ansify(*IN{IO}, *OUT{IO}, $fn);
125             if (!rename($tfn, $fn)) {
126                 warn("$fn: $!\n");
127                 unlink($tfn);
128             }
129         } else {
130             warn("$fn.ansify: $!\n");
131         }
132     } else {
133         warn("$fn: $!\n");
134     }
135 }
136
137 sub usage() {
138     print STDERR "usage: ansify [options] [file ...]
139
140 Options:
141   -c, --caddr_t                 Replace caddr_t with void * in converted
142                                 function definitions
143 ";
144     exit(1);
145 }
146
147 MAIN:{
148     Getopt::Long::Configure("auto_abbrev", "bundling");
149     GetOptions(
150                "c|caddr_t"              => \$caddr_t,
151                )
152         or usage();
153
154     if (@ARGV) {
155         foreach (@ARGV) {
156             ansify_file($_);
157         }
158     } else {
159         ansify(*STDIN{IO}, *STDOUT{IO}, "(stdin)");
160     }
161 }