blob: c78f298c4589f50484d94576c12b045f09671f33 [file] [log] [blame]
fitzhardinge7e343cd2003-12-16 02:14:00 +00001#!/usr/bin/perl
2
jseward2886b0e2004-01-04 03:46:11 +00003# This file is part of Valgrind, an extensible x86 protected-mode
4# emulator for monitoring program execution on x86-Unixes.
5#
6# Copyright (C) 2000-2004 Julian Seward
7# jseward@acm.org
8#
9# This program is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public License as
11# published by the Free Software Foundation; either version 2 of the
12# License, or (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22# 02111-1307, USA.
23#
24# The GNU General Public License is contained in the file COPYING.
25
26
fitzhardinge7e343cd2003-12-16 02:14:00 +000027my $output = shift @ARGV;
28my $indent = "";
29my $headerguard;
30my $include;
31my $passcomment = 1;
32
33my $struct = "VG_(tool_interface)";
34
35my %pfxmap = ("track" => "SK_",
36 "tool" => "SK_",
37 "malloc"=> "SK_",
38 );
39
40sub getargnames(@) {
41 my @args = @_;
42 my @ret;
43
44 foreach my $a (@args) {
45 my @pieces = split /\s+/, $a;
46 my $name = pop @pieces;
47 push @ret, $name unless $name eq "void";
48 }
49 return @ret;
50}
51
52sub getargtypes(@) {
53 my @args = @_;
54 my @ret;
55
56 foreach my $a (@args) {
57 my @pieces = split /\s+/, $a;
58 pop @pieces;
59 push @ret, (join " ", @pieces);
60 }
61 @ret = "void" if ($#ret == -1);
62 return @ret;
63}
64
65# Different output modes
66if ($output eq "callwrap") {
67 $include = "vg_include.h";
68 $generate = sub ($$$@) {
69 my ($pfx, $ret, $func, @args) = @_;
70 my $args = join ", ", @args;
71 my $argnames = join ", ", getargnames(@args);
72 print "$ret $pfxmap{$pfx}($func)($args)\n{\n";
73 print " return (*$struct.${pfx}_$func)($argnames);\n";
74 print "}\n";
75 }
76} elsif ($output eq "proto") {
77 $include = "vg_include.h";
78 $generate = sub ($$$@) {
79 my ($pfx, $ret, $func, @args) = @_;
80 my $args = join ', ', @args;
81
82 print "$ret $pfxmap{$pfx}($func)($args);\n";
83 print "Bool VG_(defined_$func)(void);\n";
84 }
85} elsif ($output eq "toolproto") {
86 $generate = sub ($$$@) {
87 my ($pfx, $ret, $func, @args) = @_;
88 my $args = join ', ', @args;
89
90 print "$ret $pfxmap{$pfx}($func)($args);\n";
91 }
92} elsif ($output eq "missingfuncs") {
93 $include = "vg_include.h";
94 $generate = sub ($$$@) {
95 my ($pfx, $ret, $func, @args) = @_;
96 my $args = join ", ", @args;
97
98 print "static $ret missing_${pfx}_$func($args) {\n";
99 print " VG_(missing_tool_func)(\"${pfx}_$func\");\n";
100 print "}\n";
101 print "Bool VG_(defined_$func)(void) {\n";
102 print " return $struct.${pfx}_$func != missing_${pfx}_$func;\n";
103 print "}\n\n";
104 };
105 $indent = " ";
106} elsif ($output eq "struct") {
107 $include = "vg_include.h";
108 $pre = sub () {
109 print "typedef struct {\n";
110 };
111 $post = sub () {
112 print "} VgToolInterface;\n\n";
113 print "extern VgToolInterface $struct;\n"
114 };
115 $generate = sub ($$$@) {
116 my ($pfx, $ret, $func, @args) = @_;
117 my $args = join ", ", @args;
118
119 print "$indent$ret (*${pfx}_$func)($args);\n";
120 };
121 $indent = " ";
122 $headerguard=$output;
123} elsif ($output eq "structdef") {
124 $include = "vg_toolint.h";
125 $pre = sub () {
126 print "VgToolInterface $struct = {\n";
127 };
128 $post = sub () {
129 print "};\n";
130 };
131 $generate = sub ($$$@) {
132 my ($pfx, $ret, $func, @args) = @_;
133
134 print "$indent.${pfx}_$func = missing_${pfx}_$func,\n"
135 };
136 $indent = " ";
137} elsif ($output eq "initfunc") {
138 $include = "vg_skin.h";
139 $generate = sub ($$$@) {
140 my ($pfx, $ret, $func, @args) = @_;
141 my $args = join ", ", @args;
142 my $argnames = join ", ", getargnames(@args);
143
144 print <<EOF;
145void VG_(init_$func)($ret (*func)($args))
146{
147 if (func == NULL)
148 func = missing_${pfx}_$func;
149 if (VG_(defined_$func)())
150 VG_(printf)("Warning tool is redefining $func\\n");
151 if (func == SK_($func))
152 VG_(printf)("Warning tool is defining $func recursively\\n");
153 $struct.${pfx}_$func = func;
154}
155EOF
156 }
157} elsif ($output eq "initproto") {
158 $generate = sub ($$$@) {
159 my ($pfx, $ret, $func, @args) = @_;
160 my $args = join ', ', @args;
161 print "void VG_(init_$func)($ret (*func)($args));\n";
162 };
163 $headerguard=$output;
164} elsif ($output eq "initdlsym") {
165 $pre = sub () {
166 print <<EOF;
167#include <dlfcn.h>
168void VG_(tool_init_dlsym)(void *dlhandle)
169{
170 void *ret;
171
172EOF
173 };
174 $post = sub () {
175 print "}\n";
176 };
177 $generate = sub ($$$@) {
178 my ($pfx, $ret, $func, @args) = @_;
179 my $args = join ", ", getargtypes(@args);
180
181 print <<EOF;
182 ret = dlsym(dlhandle, "vgSkin_$func");
183 if (ret != NULL)
184 VG_(init_$func)(($ret (*)($args))ret);
185
186EOF
187 };
188
189 $passcomment = 0;
190}
191
192die "Unknown output format \"$output\"" unless defined $generate;
193
194print "/* Generated by \"gen_toolint.pl $output\" */\n";
195
196print <<EOF if defined $headerguard;
197
198#ifndef VG_toolint_$headerguard
199#define VG_toolint_$headerguard
200
201EOF
202
203print <<EOF if defined $include;
204#include \"$include\"
205EOF
206
207&$pre() if defined $pre; # preamble
208
209my $state = "idle";
210
211my $buf;
212my $lines;
213
214while(<STDIN>) {
215 # skip simple comments
216 next if (/^#[^#]/);
217
218 if (/^:/) {
219 s/^://;
220 chomp;
221 $prefix=$_;
222 next;
223 }
224
225 # look for inserted comments
226 if (/^##/) {
227 if ($state eq "idle") {
228 $state = "comment";
229 $lines = 1;
230 $_ =~ s,^## ,/* ,;
231 $buf = $_;
232 next;
233 } elsif ($state eq "comment") {
234 $lines++;
235 $_ =~ s,^## , ,;
236 print $indent.$buf if $passcomment;
237 $buf = $_;
238 next;
239 }
240 next;
241 }
242
243 # blank lines in a comment are part of the comment
244 if (/^\s*$/) {
245 if ($state eq "comment") {
246 $lines++;
247 print $indent.$buf if $passcomment;
248 $buf = "\n";
249 } else {
250 print "\n" if $passcomment;
251 }
252 next;
253 }
254
255 # coming out of a comment
256 if ($state eq "comment") {
257 chomp $buf;
258
259 if ($passcomment) {
260 if ($lines == 1) {
261 print "$indent$buf */\n";
262 } else {
263 print "$indent$buf\n$indent */\n";
264 }
265 }
266 $buf = "";
267 $state = "idle";
268 }
269
270 chomp;
271 my @func = split /,\s*/;
272
273 my $rettype = shift @func;
274 my $funcname = shift @func;
275
276 @func = "void" if scalar @func == 0;
277
278 &$generate ($prefix, $rettype, $funcname, @func);
279}
280
281&$post() if defined $post; # postamble
282
283print <<EOF if defined $headerguard;
284
285#endif /* VG_toolint_$headerguard */
286EOF