+respected proper function calling types cdecl/stdcall/fastcall
[captive.git] / src / libcaptive / ke / captivesym.pl
1 #! /usr/bin/perl
2
3 # $Id$
4 # Generate source files based on .captivesym symbol file
5 # Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; exactly version 2 of June 1991 is required
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20
21 use vars qw($VERSION);
22 $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; };
23 use strict;
24 use warnings;
25
26
27 my %def;
28 map({ open DEF,"<$_" or die "open(\"$_\"): $!"; } shift());
29 while (<DEF>) {
30         s/;.*//s;
31         next if /^\s*$/s;
32         my($atsign,$symbol,$args,$isdata)=(/^\s*(\@)?(\S+?)(?:\@(\d+))?(\s+DATA)?\s*$/s);
33         die "Invalid line" if !defined $symbol;
34         #          popped args          doc  ntoskrnl.def
35         # cdecl    no     stack         _f   f
36         # stdcall  yes    stack         _f@4 f@4
37         # fastcall yes    ecx,edx,stack @f@4 @f@4
38         next if $isdata;
39         die "\@funcname without \@4 suffix not recognized" if $atsign && !defined $args;
40         die "Invalid \@$args number" if defined $args && ($args<0 || ($args%4));
41         die "Duplicate symbol: $symbol" if exists $def{$symbol};
42         $def{$symbol}={
43                         "type"=>(!defined $args ? "cdecl" : (!$atsign ? "stdcall" : "fastcall")),
44                         (!defined $args ? () : ("args4"=>$args/4)),
45                         };
46         }
47 close DEF or warn "close(DEF): $!";
48
49 # read source
50 my %module;     # $module{'module'}{'symbol'}=1/""
51 my %symbol;     # $symbol{'symbol'}=1/""
52 while (<>) {
53         chomp;
54         next if /^\s*$/;        # empty
55         next if /^\s*#.*/;      # comment
56         my($module,$symbol,$isundef)=(/^\s*(\S+)\s+(\S+)(\s+undef)?\s*$/);
57         die "Invalid line" if !defined $symbol;
58         die "Symbol already exists: $symbol" if exists $symbol{$symbol};
59         delete $def{$symbol} if $isundef;
60         die "Symbol not in ntoskrnl.def file: $symbol" if !$isundef && !$def{$symbol};
61         $module{$module}{$symbol}=!$isundef;
62         $symbol{$symbol}=!$isundef;
63         }
64
65 # file header
66 print <<"HERE";
67 /* File generated automatically by captivesym.pl from "$ARGV" */
68 /* DO NOT EDIT! */
69
70 #include "config.h"
71
72 #include "captive/ldr_exports.h"        /* for captive_ModuleList_add_builtin() */
73 #include <glib/gtypes.h>
74 #include <glib/gmessages.h>
75 #include <glib/gmacros.h>
76
77
78 HERE
79
80 # undefined symbol stubs
81 my $symbols_undef=0;
82 for my $symbol (sort keys(%symbol)) {
83         my $def=$def{$symbol};
84         if (!$def) {
85                 print <<"HERE";
86 static void ${symbol}_undef(void)
87 {
88         g_error("%s: Function '$symbol' NOT IMPLEMENTED",G_STRLOC);
89 }
90 HERE
91                 $symbols_undef++;
92                 }
93         elsif ("cdecl" eq $def->{"type"}) {
94                 print "void/* ==unknown */ ${symbol}(void/* ==unknown */);\n",
95                                 "#define ${symbol}_".$def->{"type"}." ${symbol}\n";
96                 }
97         else {
98                 my @args_out=map("arg$_",0..($def->{"args4"}-1));
99                 my @args_in=($def->{"type"} ne "fastcall" ? @args_out
100                                 : ("stub_eax","arg1","arg0",@args_out[2..$#args_out]));
101                 print "guint32 ${symbol}(".(join(",",map("guint32 $_",@args_out)) || "void").");\n",
102                                 "static guint32 "
103                                                                 ."__attribute__((__".(map(($_ ne "fastcall" ? $_ : "stdcall"),$def->{"type"}))[0]."__)) "
104                                                                 .($def->{"type"} ne "fastcall" ? "" : "__attribute__((__regparm__(3))) ")
105                                                                 ."${symbol}_".$def->{"type"}."(".(join(",",map("guint32 $_",@args_in)) || "void").")\n",
106                                 "{\n",
107                                 "\treturn ${symbol}(".join(",",@args_out).");\n",
108                                 "}\n";
109                 }
110         }
111
112 # export function captive_kernel_exports()
113 print <<"HERE";
114
115 gboolean captive_kernel_exports(void)
116 {
117 gboolean errbool;
118
119 HERE
120 for my $module (sort keys(%module)) {
121         my $moduleref=$module{$module};
122         print <<"HERE";
123         errbool=captive_ModuleList_add_builtin("$module",
124 HERE
125         for my $symbol (sort keys(%$moduleref)) {
126                 my $value=${$moduleref}{$symbol};
127                 print "\t\t\t\"$symbol\",&${symbol}_",
128                                 ($def{$symbol}{"type"} || "undef"),
129                                 ",\n";
130                 }
131         print <<"HERE";
132                         NULL);
133         g_return_val_if_fail(errbool,FALSE);
134
135 HERE
136         }
137 print <<"HERE";
138         return TRUE;
139 }
140 HERE
141
142 # exit
143 print STDERR "$0: Processed ".scalar(keys(%module))." modules, ".scalar(keys(%symbol))." symbols",
144                 " (".int(100*(1-$symbols_undef/scalar(keys(%symbol)))).'%'." implemented)\n";
145 print STDERR "$0: warning: $symbols_undef symbols are NOT IMPLEMENTED yet!\n" if $symbols_undef;
146 exit 0;
147
148
149 __END__
150
151 =head1 NAME
152
153 captivesym.pl - Generate source files based on .captivesym symbol file
154
155 =head1 SYNOPSIS
156
157 ./captivesym.pl path/to/ntoskrnl/ntoskrnl.def exports.captivesym E<gt>exports.c
158
159 =head1 DESCRIPTION
160
161 Source lines of I<.captivesym> file consist of lines with whitespace-separated
162 (B<module>,B<symbol>,[undef]) items.
163
164 =over
165
166 =item undef
167
168 Optional "undef" specifies invocation of a generated stub function displaying
169 C<g_error()> message.
170
171 =back
172
173 =begin comment
174
175         choose one:
176                 podchecker: *** WARNING: node 'http:$_' contains non-escaped | or /
177                 pod2html: cannot resolve L.lt.http:$_.gt.
178
179 =end comment
180
181 Source file I<ntoskrnl.def> is required to have on of three item types
182 described at
183 L<http://msdn.microsoft.com/library/en-us/vclang/html/_core_argument_passing_and_naming_conventions.asp>
184 (B<argslength> must be dividable by B<4>):
185
186 =over
187
188 =item cdecl: functionname
189
190 =item stdcall: functionname@argslength
191
192 =item fastcall: @functionname@argslength
193
194 =back
195
196 =head1 COPYRIGHT
197
198 Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
199
200 This program is free software; you can redistribute it and/or modify
201 it under the terms of the GNU General Public License as published by
202 the Free Software Foundation; exactly version 2 of June 1991 is required
203
204 This program is distributed in the hope that it will be useful,
205 but WITHOUT ANY WARRANTY; without even the implied warranty of
206 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
207 GNU General Public License for more details.
208
209 You should have received a copy of the GNU General Public License
210 along with this program; if not, write to the Free Software
211 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
212
213 =cut