blob: bc02cbe1a5d76cbc81febf15729017bdd6feff14 [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
nethercoted1c71402004-01-04 13:08:56 +000026use strict;
27use warnings;
jseward2886b0e2004-01-04 03:46:11 +000028
fitzhardinge7e343cd2003-12-16 02:14:00 +000029my $output = shift @ARGV;
30my $indent = "";
31my $headerguard;
32my $include;
33my $passcomment = 1;
nethercoted1c71402004-01-04 13:08:56 +000034my $pre;
35my $post;
36my $generate;
fitzhardinge7e343cd2003-12-16 02:14:00 +000037
38my $struct = "VG_(tool_interface)";
39
40my %pfxmap = ("track" => "SK_",
41 "tool" => "SK_",
42 "malloc"=> "SK_",
43 );
44
45sub getargnames(@) {
46 my @args = @_;
47 my @ret;
48
49 foreach my $a (@args) {
50 my @pieces = split /\s+/, $a;
51 my $name = pop @pieces;
52 push @ret, $name unless $name eq "void";
53 }
54 return @ret;
55}
56
57sub getargtypes(@) {
58 my @args = @_;
59 my @ret;
60
61 foreach my $a (@args) {
62 my @pieces = split /\s+/, $a;
63 pop @pieces;
64 push @ret, (join " ", @pieces);
65 }
66 @ret = "void" if ($#ret == -1);
67 return @ret;
68}
69
70# Different output modes
71if ($output eq "callwrap") {
nethercotef1e5e152004-09-01 23:58:16 +000072 $include = "core.h";
fitzhardinge7e343cd2003-12-16 02:14:00 +000073 $generate = sub ($$$@) {
74 my ($pfx, $ret, $func, @args) = @_;
75 my $args = join ", ", @args;
76 my $argnames = join ", ", getargnames(@args);
77 print "$ret $pfxmap{$pfx}($func)($args)\n{\n";
78 print " return (*$struct.${pfx}_$func)($argnames);\n";
79 print "}\n";
80 }
81} elsif ($output eq "proto") {
nethercotef1e5e152004-09-01 23:58:16 +000082 $include = "core.h";
fitzhardinge7e343cd2003-12-16 02:14:00 +000083 $generate = sub ($$$@) {
84 my ($pfx, $ret, $func, @args) = @_;
85 my $args = join ', ', @args;
86
87 print "$ret $pfxmap{$pfx}($func)($args);\n";
88 print "Bool VG_(defined_$func)(void);\n";
89 }
90} elsif ($output eq "toolproto") {
91 $generate = sub ($$$@) {
92 my ($pfx, $ret, $func, @args) = @_;
93 my $args = join ', ', @args;
94
95 print "$ret $pfxmap{$pfx}($func)($args);\n";
96 }
97} elsif ($output eq "missingfuncs") {
nethercotef1e5e152004-09-01 23:58:16 +000098 $include = "core.h";
fitzhardinge7e343cd2003-12-16 02:14:00 +000099 $generate = sub ($$$@) {
100 my ($pfx, $ret, $func, @args) = @_;
101 my $args = join ", ", @args;
102
103 print "static $ret missing_${pfx}_$func($args) {\n";
104 print " VG_(missing_tool_func)(\"${pfx}_$func\");\n";
105 print "}\n";
106 print "Bool VG_(defined_$func)(void) {\n";
107 print " return $struct.${pfx}_$func != missing_${pfx}_$func;\n";
108 print "}\n\n";
109 };
110 $indent = " ";
111} elsif ($output eq "struct") {
nethercotef1e5e152004-09-01 23:58:16 +0000112 $include = "core.h";
fitzhardinge7e343cd2003-12-16 02:14:00 +0000113 $pre = sub () {
114 print "typedef struct {\n";
115 };
116 $post = sub () {
117 print "} VgToolInterface;\n\n";
118 print "extern VgToolInterface $struct;\n"
119 };
120 $generate = sub ($$$@) {
121 my ($pfx, $ret, $func, @args) = @_;
122 my $args = join ", ", @args;
123
124 print "$indent$ret (*${pfx}_$func)($args);\n";
125 };
126 $indent = " ";
127 $headerguard=$output;
128} elsif ($output eq "structdef") {
129 $include = "vg_toolint.h";
130 $pre = sub () {
131 print "VgToolInterface $struct = {\n";
132 };
133 $post = sub () {
134 print "};\n";
135 };
136 $generate = sub ($$$@) {
137 my ($pfx, $ret, $func, @args) = @_;
138
139 print "$indent.${pfx}_$func = missing_${pfx}_$func,\n"
140 };
141 $indent = " ";
142} elsif ($output eq "initfunc") {
143 $include = "vg_skin.h";
144 $generate = sub ($$$@) {
145 my ($pfx, $ret, $func, @args) = @_;
146 my $args = join ", ", @args;
147 my $argnames = join ", ", getargnames(@args);
148
149 print <<EOF;
150void VG_(init_$func)($ret (*func)($args))
151{
152 if (func == NULL)
153 func = missing_${pfx}_$func;
154 if (VG_(defined_$func)())
155 VG_(printf)("Warning tool is redefining $func\\n");
156 if (func == SK_($func))
157 VG_(printf)("Warning tool is defining $func recursively\\n");
158 $struct.${pfx}_$func = func;
159}
160EOF
161 }
162} elsif ($output eq "initproto") {
163 $generate = sub ($$$@) {
164 my ($pfx, $ret, $func, @args) = @_;
165 my $args = join ', ', @args;
166 print "void VG_(init_$func)($ret (*func)($args));\n";
167 };
168 $headerguard=$output;
169} elsif ($output eq "initdlsym") {
170 $pre = sub () {
171 print <<EOF;
172#include <dlfcn.h>
173void VG_(tool_init_dlsym)(void *dlhandle)
174{
175 void *ret;
176
177EOF
178 };
179 $post = sub () {
180 print "}\n";
181 };
182 $generate = sub ($$$@) {
183 my ($pfx, $ret, $func, @args) = @_;
184 my $args = join ", ", getargtypes(@args);
185
186 print <<EOF;
187 ret = dlsym(dlhandle, "vgSkin_$func");
188 if (ret != NULL)
189 VG_(init_$func)(($ret (*)($args))ret);
190
191EOF
192 };
193
194 $passcomment = 0;
195}
196
197die "Unknown output format \"$output\"" unless defined $generate;
198
199print "/* Generated by \"gen_toolint.pl $output\" */\n";
200
201print <<EOF if defined $headerguard;
202
203#ifndef VG_toolint_$headerguard
204#define VG_toolint_$headerguard
205
206EOF
207
208print <<EOF if defined $include;
209#include \"$include\"
210EOF
211
212&$pre() if defined $pre; # preamble
213
214my $state = "idle";
215
216my $buf;
217my $lines;
nethercoted1c71402004-01-04 13:08:56 +0000218my $prefix;
fitzhardinge7e343cd2003-12-16 02:14:00 +0000219
220while(<STDIN>) {
221 # skip simple comments
222 next if (/^#[^#]/);
223
224 if (/^:/) {
225 s/^://;
226 chomp;
227 $prefix=$_;
228 next;
229 }
230
231 # look for inserted comments
232 if (/^##/) {
233 if ($state eq "idle") {
234 $state = "comment";
235 $lines = 1;
236 $_ =~ s,^## ,/* ,;
237 $buf = $_;
238 next;
239 } elsif ($state eq "comment") {
240 $lines++;
241 $_ =~ s,^## , ,;
242 print $indent.$buf if $passcomment;
243 $buf = $_;
244 next;
245 }
246 next;
247 }
248
249 # blank lines in a comment are part of the comment
250 if (/^\s*$/) {
251 if ($state eq "comment") {
252 $lines++;
253 print $indent.$buf if $passcomment;
254 $buf = "\n";
255 } else {
256 print "\n" if $passcomment;
257 }
258 next;
259 }
260
261 # coming out of a comment
262 if ($state eq "comment") {
263 chomp $buf;
264
265 if ($passcomment) {
266 if ($lines == 1) {
267 print "$indent$buf */\n";
268 } else {
269 print "$indent$buf\n$indent */\n";
270 }
271 }
272 $buf = "";
273 $state = "idle";
274 }
275
276 chomp;
277 my @func = split /,\s*/;
278
279 my $rettype = shift @func;
280 my $funcname = shift @func;
281
282 @func = "void" if scalar @func == 0;
283
284 &$generate ($prefix, $rettype, $funcname, @func);
285}
286
287&$post() if defined $post; # postamble
288
289print <<EOF if defined $headerguard;
290
291#endif /* VG_toolint_$headerguard */
292EOF