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 30use v5.6.0; 31use strict; 32 33use Getopt::Long; 34 35my $caddr_t; 36 37sub 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 115sub 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 137sub usage() { 138 print STDERR "usage: ansify [options] [file ...] 139 140Options: 141 -c, --caddr_t Replace caddr_t with void * in converted 142 function definitions 143"; 144 exit(1); 145} 146 147MAIN:{ 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} 162