mirror of
https://github.com/darlinghq/darling-Heimdal.git
synced 2024-11-23 12:19:41 +00:00
536 lines
11 KiB
Perl
536 lines
11 KiB
Perl
# Make prototypes from .c files
|
|
# $Id$
|
|
|
|
##use Getopt::Std;
|
|
require 'getopts.pl';
|
|
|
|
use JSON;
|
|
|
|
my $comment = 0;
|
|
my $doxygen = 0;
|
|
my $funcdoc = 0;
|
|
my $if_0 = 0;
|
|
my $brace = 0;
|
|
my $line = "";
|
|
my $debug = 0;
|
|
my $oproto = 1;
|
|
my $private_func_re = "^_";
|
|
my %depfunction = ();
|
|
my %exported;
|
|
my %deprecated;
|
|
my $apple = 0;
|
|
my %documentation;
|
|
|
|
Getopts('ax:m:o:p:dqE:R:P:') || die "foo";
|
|
|
|
if($opt_a) {
|
|
$apple = 1;
|
|
}
|
|
|
|
if($opt_d) {
|
|
$debug = 1;
|
|
}
|
|
|
|
if($opt_q) {
|
|
$oproto = 0;
|
|
}
|
|
|
|
if($opt_R) {
|
|
$private_func_re = $opt_R;
|
|
}
|
|
my %flags = (
|
|
'multiline-proto' => 1,
|
|
'header' => 1,
|
|
'function-blocking' => 0,
|
|
'gnuc-attribute' => 1,
|
|
'cxx' => 1
|
|
);
|
|
if($opt_m) {
|
|
foreach $i (split(/,/, $opt_m)) {
|
|
if($i eq "roken") {
|
|
$flags{"multiline-proto"} = 0;
|
|
$flags{"header"} = 0;
|
|
$flags{"function-blocking"} = 0;
|
|
$flags{"gnuc-attribute"} = 0;
|
|
$flags{"cxx"} = 0;
|
|
} else {
|
|
if(substr($i, 0, 3) eq "no-") {
|
|
$flags{substr($i, 3)} = 0;
|
|
} else {
|
|
$flags{$i} = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if($opt_x) {
|
|
my $EXP;
|
|
local $/;
|
|
open(EXP, '<', $opt_x) || die "open ${opt_x}";
|
|
my $obj = JSON->new->utf8->decode(<EXP>);
|
|
close $EXP;
|
|
|
|
foreach my $x (keys %$obj) {
|
|
if (defined $obj->{$x}->{"export"}) {
|
|
$exported{$x} = $obj->{$x};
|
|
}
|
|
if (defined $obj->{$x}->{"deprecated"}) {
|
|
$deprecated{$x} = $obj->{$x}->{"deprecated"};
|
|
}
|
|
}
|
|
}
|
|
|
|
my %defineRules = (
|
|
'HEIMDAL_DEPRECATED' =>
|
|
"#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n".
|
|
"#define HEIMDAL_DEPRECATED __attribute__((deprecated))\n".
|
|
"#elif defined(_MSC_VER) && (_MSC_VER>1200)\n".
|
|
"#define HEIMDAL_DEPRECATED __declspec(deprecated)\n".
|
|
"#else\n".
|
|
"#define HEIMDAL_DEPRECATED\n".
|
|
"#endif",
|
|
'HEIMDAL_PRINTF_ATTRIBUTE' =>
|
|
"#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n".
|
|
"#define HEIMDAL_PRINTF_ATTRIBUTE(x) __attribute__((format x))\n".
|
|
"#else\n".
|
|
"#define HEIMDAL_PRINTF_ATTRIBUTE(x)\n".
|
|
"#endif",
|
|
'HEIMDAL_NORETURN_ATTRIBUTE' =>
|
|
"#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n".
|
|
"#define HEIMDAL_NORETURN_ATTRIBUTE __attribute__((noreturn))\n".
|
|
"#else\n".
|
|
"#define HEIMDAL_NORETURN_ATTRIBUTE\n".
|
|
"#endif",
|
|
'HEIMDAL_UNUSED_ATTRIBUTE' =>
|
|
"#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n".
|
|
"#define HEIMDAL_UNUSED_ATTRIBUTE __attribute__((unused))\n".
|
|
"#else\n".
|
|
"#define HEIMDAL_UNUSED_ATTRIBUTE\n".
|
|
"#endif"
|
|
);
|
|
|
|
my %usedRules;
|
|
|
|
while(<>) {
|
|
print $brace, " ", $_ if($debug);
|
|
|
|
# Handle C comments
|
|
s@/\*.*\*/@@;
|
|
s@//.*/@@;
|
|
if ( s@/\*\*(.*)@@) { $comment = 1; $doxygen = 1; $funcdoc = $1;
|
|
} elsif ( s@/\*.*@@) { $comment = 1;
|
|
} elsif ($comment && s@.*\*/@@) { $comment = 0; $doxygen = 0;
|
|
} elsif ($doxygen) { $funcdoc .= $_; next;
|
|
} elsif ($comment) { next; }
|
|
|
|
if(/^\#if 0/) {
|
|
$if_0 = 1;
|
|
}
|
|
if($if_0 && /^\#endif/) {
|
|
$if_0 = 0;
|
|
}
|
|
if($if_0) { next }
|
|
if(/^\s*\#/) {
|
|
next;
|
|
}
|
|
if(/^\s*$/) {
|
|
$line = "";
|
|
next;
|
|
}
|
|
if(/\{/){
|
|
if (!/\}/) {
|
|
$brace++;
|
|
}
|
|
$_ = $line;
|
|
while(s/\*\//\ca/){
|
|
s/\/\*(.|\n)*\ca//;
|
|
}
|
|
s/^\s*//;
|
|
s/\s*$//;
|
|
s/\s+/ /g;
|
|
if($_ =~ /\)/){
|
|
if(!/^static/ && !/^PRIVATE/){
|
|
$attr = "";
|
|
if(m/(.*)(__attribute__\s?\(.*\))/) {
|
|
$attr .= " $2";
|
|
$_ = $1;
|
|
}
|
|
if(m/(.*)\s(\w+DEPRECATED_FUNCTION)\s?(\(.*\))(.*)/) {
|
|
$depfunction{$2} = 1;
|
|
$attr .= " $2$3";
|
|
$_ = "$1 $4";
|
|
}
|
|
if(m/(.*)\s(\w+__nullable)(.*)/) {
|
|
$attr .= " $2";
|
|
$_ = "$1 $3";
|
|
}
|
|
if(m/(.*)\s(\w+__nonnull)(.*)/) {
|
|
$usedRules{$2} = 1;
|
|
$attr .= " $2";
|
|
$_ = "$1 $3";
|
|
}
|
|
if(m/(.*)\s(\w+DEPRECATED)(.*)/) {
|
|
$usedRules{$2} = 1;
|
|
$attr .= " $2";
|
|
$_ = "$1 $3";
|
|
}
|
|
if(m/(.*)\s(HEIMDAL_\w+_ATTRIBUTE)\s?(\(.*\))?(.*)/) {
|
|
$usedRules{$2} = 1;
|
|
$attr .= " $2$3";
|
|
$_ = "$1 $4";
|
|
}
|
|
# remove outer ()
|
|
s/\s*\(/</;
|
|
s/\)\s?$/>/;
|
|
# remove , within ()
|
|
while(s/\(([^()]*),(.*)\)/($1\$$2)/g){}
|
|
s/\<\s*void\s*\>/<>/;
|
|
# remove parameter names
|
|
if($opt_P eq "remove") {
|
|
s/(\s*)([a-zA-Z0-9_]+)([,>])/$3/g;
|
|
s/\s+\*/*/g;
|
|
s/\(\*(\s*)([a-zA-Z0-9_]+)\)/(*)/g;
|
|
} elsif($opt_P eq "comment") {
|
|
s/([a-zA-Z0-9_]+)([,>])/\/\*$1\*\/$2/g;
|
|
s/\(\*([a-zA-Z0-9_]+)\)/(*\/\*$1\*\/)/g;
|
|
}
|
|
s/\<\>/<void>/;
|
|
# add newlines before parameters
|
|
if($flags{"multiline-proto"}) {
|
|
s/,\s*/,\n\t/g;
|
|
} else {
|
|
s/,\s*/, /g;
|
|
}
|
|
# fix removed ,
|
|
s/\$/,/g;
|
|
# match function name
|
|
/([a-zA-Z0-9_]+)\s*\</;
|
|
$f = $1;
|
|
if($oproto) {
|
|
$LP = "__P((";
|
|
$RP = "))";
|
|
} else {
|
|
$LP = "(";
|
|
$RP = ")";
|
|
}
|
|
# only add newline if more than one parameter
|
|
if($flags{"multiline-proto"} && /,/){
|
|
s/\</ $LP\n\t/;
|
|
}else{
|
|
s/\</ $LP/;
|
|
}
|
|
s/\>/$RP/;
|
|
# insert newline before function name
|
|
if($flags{"multiline-proto"}) {
|
|
s/(.*)\s([a-zA-Z0-9_]+ \Q$LP\E)/$1\n$2/;
|
|
}
|
|
if($attr ne "") {
|
|
$_ .= "\n $attr";
|
|
}
|
|
if ($funcdoc) {
|
|
$documentation{$f} = $funcdoc;
|
|
}
|
|
$funcdoc = undef;
|
|
if ($apple && exists $exported{$f}) {
|
|
$ios = $exported{$f}{ios};
|
|
$ios = "NA" if (!defined $ios);
|
|
$mac = $exported{$f}{macos};
|
|
$mac = "NA" if (!defined $mac);
|
|
die "$f neither" if ($mac eq "NA" and $ios eq "NA");
|
|
|
|
if (exists $exported{$f}{deprecated}) {
|
|
$iosDep = $exported{$f}{iosDep};
|
|
if ($ios eq "NA") {
|
|
$iosDep = "NA";
|
|
}
|
|
|
|
$macDep = $exported{$f}{macosDep};
|
|
if ($mac eq "NA") {
|
|
$macDep = "NA";
|
|
}
|
|
|
|
$_ = $_ . " __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_${mac}, __MAC_${macDep}, __IPHONE_${ios}, __IPHONE_${iosDep}, \"$exported{$f}{deprecated}\")";
|
|
} else {
|
|
$_ = $_ . " __OSX_AVAILABLE_STARTING(__MAC_${mac}, __IPHONE_${ios})";
|
|
}
|
|
}
|
|
print "found function $f\n" if($debug);
|
|
if (exists $deprecated{$f} && !$apple && exists $exported{$f}) {
|
|
$_ = $_ . " GSSAPI_DEPRECATED_FUNCTION(\"$deprecated{$f}\")";
|
|
$depfunction{GSSAPI_DEPRECATED_FUNCTION} = 1;
|
|
}
|
|
$_ = $_ . ";";
|
|
$funcs{$f} = $_;
|
|
}
|
|
}
|
|
$line = "";
|
|
}
|
|
if(/\}/){
|
|
$brace--;
|
|
}
|
|
if(/^\}/){
|
|
$brace = 0;
|
|
}
|
|
if($brace == 0) {
|
|
$line = $line . " " . $_;
|
|
}
|
|
}
|
|
|
|
die "reached end of code and still in doxygen comment" if ($doxygen);
|
|
die "reached end of code and still in comment" if ($comment);
|
|
|
|
sub foo {
|
|
local ($arg) = @_;
|
|
$_ = $arg;
|
|
s/.*\/([^\/]*)/$1/;
|
|
s/.*\\([^\\]*)/$1/;
|
|
s/[^a-zA-Z0-9]/_/g;
|
|
"__" . $_ . "__";
|
|
}
|
|
|
|
if($opt_o) {
|
|
open(OUT, ">$opt_o");
|
|
$block = &foo($opt_o);
|
|
} else {
|
|
$block = "__public_h__";
|
|
}
|
|
|
|
if($opt_p) {
|
|
open(PRIV, ">$opt_p");
|
|
$private = &foo($opt_p);
|
|
} else {
|
|
$private = "__private_h__";
|
|
}
|
|
|
|
$public_h = "";
|
|
$private_h = "";
|
|
|
|
$public_h_header .= "/* This is a generated file */
|
|
#ifndef $block
|
|
#define $block
|
|
|
|
";
|
|
if ($oproto) {
|
|
$public_h_header .= "#ifdef __STDC__
|
|
#include <stdarg.h>
|
|
#ifndef __P
|
|
#define __P(x) x
|
|
#endif
|
|
#else
|
|
#ifndef __P
|
|
#define __P(x) ()
|
|
#endif
|
|
#endif
|
|
|
|
";
|
|
} else {
|
|
$public_h_header .= "#include <stdarg.h>
|
|
|
|
";
|
|
}
|
|
$public_h_trailer = "";
|
|
|
|
$private_h_header = "/* This is a generated file */
|
|
#ifndef $private
|
|
#define $private
|
|
|
|
";
|
|
if($oproto) {
|
|
$private_h_header .= "#ifdef __STDC__
|
|
#include <stdarg.h>
|
|
#ifndef __P
|
|
#define __P(x) x
|
|
#endif
|
|
#else
|
|
#ifndef __P
|
|
#define __P(x) ()
|
|
#endif
|
|
#endif
|
|
|
|
";
|
|
} else {
|
|
$private_h_header .= "#include <stdarg.h>
|
|
|
|
";
|
|
}
|
|
$private_h_trailer = "";
|
|
|
|
foreach(sort keys %usedRules) {
|
|
next if not exists $defineRules{$_};
|
|
|
|
my $var = "#ifndef $_
|
|
$defineRules{$_}
|
|
#endif
|
|
|
|
";
|
|
|
|
$private_h_header .= $var;
|
|
$public_h_header .= $var;
|
|
}
|
|
|
|
foreach(sort keys %funcs){
|
|
if(/^(DllMain|main)$/) { next }
|
|
if ($funcs{$_} =~ /\^/) {
|
|
$beginblock = "#ifdef __BLOCKS__\n";
|
|
$endblock = "#endif /* __BLOCKS__ */\n";
|
|
} else {
|
|
$beginblock = $endblock = "";
|
|
}
|
|
# if we have an export table and doesn't have content, or matches private RE
|
|
if(((scalar keys %exported) ne 0 && !exists $exported{$_} ) || /$private_func_re/) {
|
|
$private_h .= $beginblock;
|
|
# if ($apple and not /$private_func_re/) {
|
|
# $private_h .= "#define $_ __ApplePrivate_${_}\n";
|
|
# }
|
|
$private_h .= $funcs{$_} . "\n" ;
|
|
$private_h .= $endblock . "\n";
|
|
if($funcs{$_} =~ /__attribute__/) {
|
|
$private_attribute_seen = 1;
|
|
}
|
|
} else {
|
|
if($documentation{$_}) {
|
|
$public_h .= "/**\n";
|
|
$public_h .= "$documentation{$_}";
|
|
$public_h .= " */\n\n";
|
|
}
|
|
if($flags{"function-blocking"}) {
|
|
$fupper = uc $_;
|
|
if($exported{$_} =~ /proto/) {
|
|
$public_h .= "#if !defined(HAVE_$fupper) || defined(NEED_${fupper}_PROTO)\n";
|
|
} else {
|
|
$public_h .= "#ifndef HAVE_$fupper\n";
|
|
}
|
|
}
|
|
$public_h .= $beginblock . $funcs{$_} . "\n" . $endblock;
|
|
if($funcs{$_} =~ /__attribute__/) {
|
|
$public_attribute_seen = 1;
|
|
}
|
|
if($flags{"function-blocking"}) {
|
|
$public_h .= "#endif\n";
|
|
}
|
|
$public_h .= "\n";
|
|
}
|
|
}
|
|
|
|
if($flags{"gnuc-attribute"}) {
|
|
if ($public_attribute_seen) {
|
|
$public_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
|
|
#define __attribute__(x)
|
|
#endif
|
|
|
|
";
|
|
}
|
|
|
|
if ($private_attribute_seen) {
|
|
$private_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
|
|
#define __attribute__(x)
|
|
#endif
|
|
|
|
";
|
|
}
|
|
}
|
|
|
|
my $depstr = "";
|
|
my $undepstr = "";
|
|
foreach (keys %depfunction) {
|
|
$depstr .= "#ifndef $_
|
|
#ifndef __has_extension
|
|
#define __has_extension(x) 0
|
|
#define ${_}has_extension 1
|
|
#endif
|
|
#if __has_extension(attribute_deprecated_with_message)
|
|
#define $_(x) __attribute__((__deprecated__(x)))
|
|
#elif defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))
|
|
#define $_(X) __attribute__((__deprecated__))
|
|
#else
|
|
#define $_(X)
|
|
#endif
|
|
#ifdef ${_}has_extension
|
|
#undef __has_extension
|
|
#undef ${_}has_extension
|
|
#endif
|
|
#endif /* $_ */
|
|
|
|
|
|
";
|
|
$public_h_trailer .= "#undef $_
|
|
|
|
";
|
|
$private_h_trailer .= "#undef $_
|
|
#define $_(X)
|
|
|
|
";
|
|
}
|
|
|
|
$public_h_header .= $depstr;
|
|
$private_h_header .= $depstr;
|
|
|
|
|
|
if($flags{"cxx"}) {
|
|
$public_h_header .= "#ifdef __cplusplus
|
|
extern \"C\" {
|
|
#endif
|
|
|
|
";
|
|
$public_h_trailer = "#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
" . $public_h_trailer;
|
|
|
|
}
|
|
if ($opt_E) {
|
|
$public_h_header .= "#ifndef $opt_E
|
|
#ifndef ${opt_E}_FUNCTION
|
|
#if defined(_WIN32)
|
|
#define ${opt_E}_FUNCTION __declspec(dllimport)
|
|
#define ${opt_E}_CALL __stdcall
|
|
#define ${opt_E}_VARIABLE __declspec(dllimport)
|
|
#else
|
|
#define ${opt_E}_FUNCTION
|
|
#define ${opt_E}_CALL
|
|
#define ${opt_E}_VARIABLE
|
|
#endif
|
|
#endif
|
|
#endif
|
|
";
|
|
|
|
$private_h_header .= "#ifndef $opt_E
|
|
#ifndef ${opt_E}_FUNCTION
|
|
#if defined(_WIN32)
|
|
#define ${opt_E}_FUNCTION __declspec(dllimport)
|
|
#define ${opt_E}_CALL __stdcall
|
|
#define ${opt_E}_VARIABLE __declspec(dllimport)
|
|
#else
|
|
#define ${opt_E}_FUNCTION
|
|
#define ${opt_E}_CALL
|
|
#define ${opt_E}_VARIABLE
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
";
|
|
}
|
|
|
|
$public_h_trailer .= $undepstr;
|
|
$private_h_trailer .= $undepstr;
|
|
|
|
if ($public_h ne "" && $flags{"header"}) {
|
|
$public_h = $public_h_header . $public_h .
|
|
$public_h_trailer . "#endif /* $block */\n";
|
|
}
|
|
if ($private_h ne "" && $flags{"header"}) {
|
|
$private_h = $private_h_header . $private_h .
|
|
$private_h_trailer . "#endif /* $private */\n";
|
|
}
|
|
|
|
if($opt_o) {
|
|
print OUT $public_h;
|
|
}
|
|
if($opt_p) {
|
|
print PRIV $private_h;
|
|
}
|
|
|
|
close OUT;
|
|
close PRIV;
|