11573Srgrimes#!/usr/bin/perl -w
21573Srgrimes#-
31573Srgrimes# Copyright (c) 2005 Dag-Erling Co��dan Sm��rgrav
41573Srgrimes# All rights reserved.
51573Srgrimes#
61573Srgrimes# Redistribution and use in source and binary forms, with or without
71573Srgrimes# modification, are permitted provided that the following conditions
81573Srgrimes# are met:
91573Srgrimes# 1. Redistributions of source code must retain the above copyright
101573Srgrimes#    notice, this list of conditions and the following disclaimer
111573Srgrimes#    in this position and unchanged.
121573Srgrimes# 2. Redistributions in binary form must reproduce the above copyright
131573Srgrimes#    notice, this list of conditions and the following disclaimer in the
141573Srgrimes#    documentation and/or other materials provided with the distribution.
151573Srgrimes#
161573Srgrimes# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171573Srgrimes# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181573Srgrimes# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191573Srgrimes# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201573Srgrimes# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211573Srgrimes# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221573Srgrimes# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231573Srgrimes# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241573Srgrimes# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251573Srgrimes# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261573Srgrimes# SUCH DAMAGE.
271573Srgrimes#
281573Srgrimes# $FreeBSD$
291573Srgrimes#
301573Srgrimes
311573Srgrimesuse v5.6.0;
321573Srgrimesuse strict;
3392889Sobrien
3492889Sobrienuse Getopt::Long;
351573Srgrimes
36157779Sumemy $caddr_t;
371573Srgrimes
381573Srgrimessub ansify($$$) {
39157779Sume    my $ifh = shift;
40149313Sstefanf    my $ofh = shift;
411573Srgrimes    my $fn = shift;
42158115Sume
431573Srgrimes    my $line = 0;
441573Srgrimes  OUTER:
451573Srgrimes    while (<$ifh>) {
46145279Sume	# look for K&R-style function definitions
47145279Sume	if (m/^(\w+)\s*\(([\w,\s]+)\)$/) {
48145279Sume	    my @saved = ($_);
49145279Sume	    my $func = $1;
50158115Sume	    my @args = split(/\s*,\s*/, $2);
51158115Sume	    my $arglist = "";
52158115Sume	    # capture K&R-style argument list
53158115Sume	    while (<$ifh>) {
541573Srgrimes		push(@saved, $_);
55158115Sume		last if (m/^\{\s*$/);
56158115Sume		$arglist .= $_;
57158115Sume	    }
58158115Sume	    # remove comments (common in vfs code)
59158115Sume	    $arglist =~ s/\/\*([^*]|\*[^\/])*\*\// /gs;
60157779Sume	    # identify type of each argument
61157779Sume	    my %type;
621573Srgrimes	    foreach (split('\n', $arglist)) {
63145279Sume		s/\s+/ /g;
64145279Sume		if (!/^\s*([\w\s\*]+?)\s*(\w+?);\s*$/) {
65145279Sume		    warn("[$fn:$line] $func(): can't parse argument list\n");
66145279Sume		    print $ofh @saved;
67145279Sume		    $line += @saved;
68145279Sume		    next OUTER;
69145279Sume		}
70145279Sume		$type{$2} = $1;
711573Srgrimes	    }
72145279Sume	    # construct ANSI-style function definition
73157779Sume	    my $repl = "$func(";
74145279Sume	    foreach my $arg (@args) {
75157779Sume		# missing arguments in argument list
76145279Sume		if (!exists($type{$arg})) {
77157779Sume		    warn("[$fn:$line] $func(): unknown type for '$arg' argument\n");
78157779Sume		    print $ofh @saved;
79145279Sume		    $line += @saved;
80145279Sume		    next OUTER;
81145279Sume		}
82157779Sume		if ($caddr_t) {
83145279Sume		    $type{$arg} = "void *"
84157779Sume			if $type{$arg} eq "caddr_t";
85145279Sume		}
86145279Sume		$repl .= $type{$arg};
87158115Sume		$repl .= " "
88157779Sume		    unless ($type{$arg} =~ m/\*$/);
89158115Sume		$repl .= $arg;
90158115Sume		$repl .= ", "
91158115Sume		    unless $arg eq $args[-1];
92158115Sume		delete $type{$arg};
93158115Sume	    }
94158115Sume	    $repl .= ")";
95158115Sume	    # extra arguments in argument list
96158115Sume	    if (%type) {
97158115Sume		warn("[$fn:$line] $func(): too many arguments\n");
98158115Sume		print $ofh @saved;
99158115Sume		$line += @saved;
100158115Sume		next OUTER;
101158115Sume	    }
102158115Sume	    print $ofh "$repl\n";
103158115Sume	    ++$line;
104158115Sume	    # warn about long lines so they can be fixed up manually
105158115Sume	    warn("[$fn:$line] $func(): definition exceeds 80 characters\n")
106158115Sume		if length($repl) >= 80;
107158115Sume	    print $ofh "{\n";
108158115Sume	    ++$line;
109158115Sume	} else {
110158115Sume	    print $ofh $_;
111158115Sume	    ++$line;
112158115Sume	}
113158115Sume    }
114158115Sume}
115158115Sume
116158115Sumesub ansify_file($) {
117158115Sume    my $fn = shift;
118158115Sume
119158115Sume    my $tfn = "$fn.ansify";
120158115Sume    local *IN;
121158115Sume    local *OUT;
122158115Sume
123158115Sume    if (open(IN, "<", $fn)) {
124158115Sume	if (open(OUT, ">", $tfn)) {
125158115Sume	    ansify(*IN{IO}, *OUT{IO}, $fn);
126158115Sume	    if (!rename($tfn, $fn)) {
127158115Sume		warn("$fn: $!\n");
128158115Sume		unlink($tfn);
129158115Sume	    }
130158115Sume	} else {
131158115Sume	    warn("$fn.ansify: $!\n");
132158115Sume	}
133158115Sume    } else {
134158115Sume	warn("$fn: $!\n");
135158115Sume    }
136158115Sume}
137158115Sume
138158115Sumesub usage() {
139158115Sume    print STDERR "usage: ansify [options] [file ...]
140158115Sume
141158115SumeOptions:
142158115Sume  -c, --caddr_t                 Replace caddr_t with void * in converted
143158115Sume                                function definitions
144158115Sume";
145158115Sume    exit(1);
146158115Sume}
147158115Sume
148158115SumeMAIN:{
149158115Sume    Getopt::Long::Configure("auto_abbrev", "bundling");
150158115Sume    GetOptions(
151158115Sume	       "c|caddr_t"		=> \$caddr_t,
152158115Sume	       )
153158115Sume	or usage();
154158115Sume
155158115Sume    if (@ARGV) {
156158115Sume	foreach (@ARGV) {
157158115Sume	    ansify_file($_);
158158115Sume	}
159158115Sume    } else {
160158115Sume	ansify(*STDIN{IO}, *STDOUT{IO}, "(stdin)");
161158115Sume    }
162158115Sume}
163158115Sume