]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/tools/ansify/ansify.pl
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / tools / ansify / ansify.pl
1 #!/usr/bin/perl -w
2 #-
3 # Copyright (c) 2005 Dag-Erling Coïdan 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 # $FreeBSD$
29 #
30
31 use v5.6.0;
32 use strict;
33
34 use Getopt::Long;
35
36 my $caddr_t;
37
38 sub ansify($$$) {
39     my $ifh = shift;
40     my $ofh = shift;
41     my $fn = shift;
42
43     my $line = 0;
44   OUTER:
45     while (<$ifh>) {
46         # look for K&R-style function definitions
47         if (m/^(\w+)\s*\(([\w,\s]+)\)$/) {
48             my @saved = ($_);
49             my $func = $1;
50             my @args = split(/\s*,\s*/, $2);
51             my $arglist = "";
52             # capture K&R-style argument list
53             while (<$ifh>) {
54                 push(@saved, $_);
55                 last if (m/^\{\s*$/);
56                 $arglist .= $_;
57             }
58             # remove comments (common in vfs code)
59             $arglist =~ s/\/\*([^*]|\*[^\/])*\*\// /gs;
60             # identify type of each argument
61             my %type;
62             foreach (split('\n', $arglist)) {
63                 s/\s+/ /g;
64                 if (!/^\s*([\w\s\*]+?)\s*(\w+?);\s*$/) {
65                     warn("[$fn:$line] $func(): can't parse argument list\n");
66                     print $ofh @saved;
67                     $line += @saved;
68                     next OUTER;
69                 }
70                 $type{$2} = $1;
71             }
72             # construct ANSI-style function definition
73             my $repl = "$func(";
74             foreach my $arg (@args) {
75                 # missing arguments in argument list
76                 if (!exists($type{$arg})) {
77                     warn("[$fn:$line] $func(): unknown type for '$arg' argument\n");
78                     print $ofh @saved;
79                     $line += @saved;
80                     next OUTER;
81                 }
82                 if ($caddr_t) {
83                     $type{$arg} = "void *"
84                         if $type{$arg} eq "caddr_t";
85                 }
86                 $repl .= $type{$arg};
87                 $repl .= " "
88                     unless ($type{$arg} =~ m/\*$/);
89                 $repl .= $arg;
90                 $repl .= ", "
91                     unless $arg eq $args[-1];
92                 delete $type{$arg};
93             }
94             $repl .= ")";
95             # extra arguments in argument list
96             if (%type) {
97                 warn("[$fn:$line] $func(): too many arguments\n");
98                 print $ofh @saved;
99                 $line += @saved;
100                 next OUTER;
101             }
102             print $ofh "$repl\n";
103             ++$line;
104             # warn about long lines so they can be fixed up manually
105             warn("[$fn:$line] $func(): definition exceeds 80 characters\n")
106                 if length($repl) >= 80;
107             print $ofh "{\n";
108             ++$line;
109         } else {
110             print $ofh $_;
111             ++$line;
112         }
113     }
114 }
115
116 sub ansify_file($) {
117     my $fn = shift;
118
119     my $tfn = "$fn.ansify";
120     local *IN;
121     local *OUT;
122
123     if (open(IN, "<", $fn)) {
124         if (open(OUT, ">", $tfn)) {
125             ansify(*IN{IO}, *OUT{IO}, $fn);
126             if (!rename($tfn, $fn)) {
127                 warn("$fn: $!\n");
128                 unlink($tfn);
129             }
130         } else {
131             warn("$fn.ansify: $!\n");
132         }
133     } else {
134         warn("$fn: $!\n");
135     }
136 }
137
138 sub usage() {
139     print STDERR "usage: ansify [options] [file ...]
140
141 Options:
142   -c, --caddr_t                 Replace caddr_t with void * in converted
143                                 function definitions
144 ";
145     exit(1);
146 }
147
148 MAIN:{
149     Getopt::Long::Configure("auto_abbrev", "bundling");
150     GetOptions(
151                "c|caddr_t"              => \$caddr_t,
152                )
153         or usage();
154
155     if (@ARGV) {
156         foreach (@ARGV) {
157             ansify_file($_);
158         }
159     } else {
160         ansify(*STDIN{IO}, *STDOUT{IO}, "(stdin)");
161     }
162 }