genprotocol.pl 3.0 KB
Newer Older
1 2 3
#
# Generate code for an XDR protocol, optionally applying
# fixups to the glibc rpcgen code so that it compiles
4 5 6 7 8 9 10
# with warnings turned on.
#
# This code is evil.  Arguably better would be just to compile
# without -Werror.  Update: The IXDR_PUT_LONG replacements are
# actually fixes for 64 bit, so this file is necessary.  Arguably
# so is the type-punning fix.
#
11
# Copyright (C) 2007, 2011 Red Hat, Inc.
12 13 14 15 16 17 18 19 20 21
#
# See COPYING for the license of this software.
#
# Richard Jones <rjones@redhat.com>

use strict;

my $in_function = 0;
my @function = ();

22 23 24 25 26 27 28 29 30 31 32 33
my $rpcgen = shift;
my $mode = shift;
my $xdrdef = shift;
my $target = shift;

unlink $target;

open RPCGEN, "-|", $rpcgen, $mode, $xdrdef
    or die "cannot run $rpcgen $mode $xdrdef: $!";
open TARGET, ">$target"
    or die "cannot create $target: $!";

E
Eric Blake 已提交
34
my $fixup = $^O eq "linux" || $^O eq "cygwin";
35 36 37 38 39 40 41 42 43 44 45 46 47

if ($mode eq "-c") {
    print TARGET "#include <config.h>\n";
}

while (<RPCGEN>) {
    # We only want to fixup the GLibc rpcgen output
    # So just print data unchanged, if non-Linux
    unless ($fixup) {
	print TARGET;
	next;
    }

48 49
    if (m/^{/) {
	$in_function = 1;
50
	print TARGET;
51 52 53
	next;
    }

54 55
    s/\t/        /g;

56 57 58 59 60
    # Portability for Solaris RPC
    s/u_quad_t/uint64_t/g;
    s/quad_t/int64_t/g;
    s/xdr_u_quad_t/xdr_uint64_t/g;
    s/xdr_quad_t/xdr_int64_t/g;
61
    s/(?<!IXDR_GET_INT32 )IXDR_GET_LONG/IXDR_GET_INT32/g;
E
Eric Blake 已提交
62
    s,#include ".*remote/remote_protocol\.h",#include "remote_protocol.h",;
63

64 65 66 67 68 69
    if (m/^}/) {
	$in_function = 0;

	# Note: The body of the function is in @function.

	# Remove decl of buf, if buf isn't used in the function.
70 71
	my @uses = grep /[^.>]\bbuf\b/, @function;
	@function = grep !/[^.>]\bbuf\b/, @function if @uses == 1;
72 73

	# Remove decl of i, if i isn't used in the function.
74 75
	@uses = grep /[^.>]\bi\b/, @function;
	@function = grep !/[^.>]\bi\b/, @function if @uses == 1;
76 77 78 79 80 81 82 83

	# (char **)&objp->... gives:
	# warning: dereferencing type-punned pointer will break
	#   strict-aliasing rules
	# so rewrite it.
	my %uses = ();
	my $i = 0;
	foreach (@function) {
84
	    $uses{$1} = $i++ if m/\(char \*\*\)\&(objp->[a-z_.]+_val)/i;
85 86 87 88 89 90 91
	}
	if (keys %uses >= 1) {
	    my $i = 1;

	    foreach (keys %uses) {
		$i = $uses{$_};
		unshift @function,
92
		("        char **objp_cpp$i = (char **) (void *) &$_;\n");
93 94 95 96
		$i++;
	    }
	    @function =
		map { s{\(char \*\*\)\&(objp->[a-z_.]+_val)}
97
		       {objp_cpp$uses{$1}}gi; $_ } @function;
98 99 100 101 102 103 104 105
	}

	# The code uses 'IXDR_PUT_{U_,}LONG' but it's wrong in two
	# ways: Firstly these functions are deprecated and don't
	# work on 64 bit platforms.  Secondly the return value should
	# be ignored.  Correct both these mistakes.
	@function =
	    map { s/\bIXDR_PUT_((U_)?)LONG\b/(void)IXDR_PUT_$1INT32/; $_ }
106
	    map { s/\bXDR_INLINE\b/(int32_t*)XDR_INLINE/; $_ }
107 108
	    @function;

109
	print TARGET (join ("", @function));
110 111 112 113
	@function = ();
    }

    unless ($in_function) {
114
	print TARGET;
115 116 117 118
    } else {
	push @function, $_;
    }
}
119 120 121 122 123 124 125 126

close TARGET
    or die "cannot save $target: $!";
close RPCGEN
    or die "cannot shutdown $rpcgen: $!";

chmod 0444, $target
    or die "cannot set $target readonly: $!";