1f59d82ffSelric# Make prototypes from .c files 2fcfd9267Selric# Id 3f59d82ffSelric 4603f2576Spettaiuse Getopt::Std; 5603f2576Spettaiuse File::Compare; 6f59d82ffSelric 7*e0895134Schristosuse JSON; 8*e0895134Schristos 9f59d82ffSelricmy $comment = 0; 10*e0895134Schristosmy $doxygen = 0; 11*e0895134Schristosmy $funcdoc = 0; 12f59d82ffSelricmy $if_0 = 0; 13f59d82ffSelricmy $brace = 0; 14f59d82ffSelricmy $line = ""; 15f59d82ffSelricmy $debug = 0; 16f59d82ffSelricmy $oproto = 1; 17f59d82ffSelricmy $private_func_re = "^_"; 18*e0895134Schristosmy %depfunction; 19*e0895134Schristosmy %exported; 20*e0895134Schristosmy %deprecated; 21*e0895134Schristosmy $apple = 0; 22*e0895134Schristosmy %documentation; 23f59d82ffSelric 24603f2576Spettaigetopts('x:m:o:p:dqE:R:P:') || die "foo"; 25*e0895134Schristosif($opt_a) { 26*e0895134Schristos $apple = 1; 27*e0895134Schristos} 28*e0895134Schristos 29*e0895134Schristosif($opt_a) { 30*e0895134Schristos $apple = 1; 31*e0895134Schristos} 32f59d82ffSelric 33f59d82ffSelricif($opt_d) { 34f59d82ffSelric $debug = 1; 35f59d82ffSelric} 36f59d82ffSelric 37f59d82ffSelricif($opt_q) { 38f59d82ffSelric $oproto = 0; 39f59d82ffSelric} 40f59d82ffSelric 41f59d82ffSelricif($opt_R) { 42f59d82ffSelric $private_func_re = $opt_R; 43f59d82ffSelric} 44603f2576Spettaimy %flags = ( 45f59d82ffSelric 'multiline-proto' => 1, 46f59d82ffSelric 'header' => 1, 47f59d82ffSelric 'function-blocking' => 0, 48f59d82ffSelric 'gnuc-attribute' => 1, 49f59d82ffSelric 'cxx' => 1 50f59d82ffSelric ); 51f59d82ffSelricif($opt_m) { 52f59d82ffSelric foreach $i (split(/,/, $opt_m)) { 53f59d82ffSelric if($i eq "roken") { 54f59d82ffSelric $flags{"multiline-proto"} = 0; 55f59d82ffSelric $flags{"header"} = 0; 56f59d82ffSelric $flags{"function-blocking"} = 0; 57f59d82ffSelric $flags{"gnuc-attribute"} = 0; 58f59d82ffSelric $flags{"cxx"} = 0; 59f59d82ffSelric } else { 60f59d82ffSelric if(substr($i, 0, 3) eq "no-") { 61f59d82ffSelric $flags{substr($i, 3)} = 0; 62f59d82ffSelric } else { 63f59d82ffSelric $flags{$i} = 1; 64f59d82ffSelric } 65f59d82ffSelric } 66f59d82ffSelric } 67f59d82ffSelric} 68f59d82ffSelric 69f59d82ffSelricif($opt_x) { 70*e0895134Schristos my $EXP; 71*e0895134Schristos local $/; 72*e0895134Schristos open(EXP, '<', $opt_x) || die "open ${opt_x}"; 73*e0895134Schristos my $obj = JSON->new->utf8->decode(<EXP>); 74*e0895134Schristos close $EXP; 75*e0895134Schristos 76*e0895134Schristos foreach my $x (keys %$obj) { 77*e0895134Schristos if (defined $obj->{$x}->{"export"}) { 78*e0895134Schristos $exported{$x} = $obj->{$x}; 79*e0895134Schristos } 80*e0895134Schristos if (defined $obj->{$x}->{"deprecated"}) { 81*e0895134Schristos $deprecated{$x} = $obj->{$x}->{"deprecated"}; 82f59d82ffSelric } 83f59d82ffSelric } 84f59d82ffSelric} 85f59d82ffSelric 86f59d82ffSelricwhile(<>) { 87f59d82ffSelric print $brace, " ", $_ if($debug); 88f59d82ffSelric 89f59d82ffSelric # Handle C comments 90f59d82ffSelric s@/\*.*\*/@@; 91f59d82ffSelric s@//.*/@@; 92*e0895134Schristos if ( s@/\*\*(.*)@@) { $comment = 1; $doxygen = 1; $funcdoc = $1; 93*e0895134Schristos } elsif ( s@/\*.*@@) { $comment = 1; 94*e0895134Schristos } elsif ($comment && s@.*\*/@@) { $comment = 0; $doxygen = 0; 95*e0895134Schristos } elsif ($doxygen) { $funcdoc .= $_; next; 96f59d82ffSelric } elsif ($comment) { next; } 97f59d82ffSelric 98f59d82ffSelric if(/^\#if 0/) { 99f59d82ffSelric $if_0 = 1; 100f59d82ffSelric } 101f59d82ffSelric if($if_0 && /^\#endif/) { 102f59d82ffSelric $if_0 = 0; 103f59d82ffSelric } 104f59d82ffSelric if($if_0) { next } 105f59d82ffSelric if(/^\s*\#/) { 106f59d82ffSelric next; 107f59d82ffSelric } 108f59d82ffSelric if(/^\s*$/) { 109f59d82ffSelric $line = ""; 110f59d82ffSelric next; 111f59d82ffSelric } 112f59d82ffSelric if(/\{/){ 113f59d82ffSelric if (!/\}/) { 114f59d82ffSelric $brace++; 115f59d82ffSelric } 116f59d82ffSelric $_ = $line; 117f59d82ffSelric while(s/\*\//\ca/){ 118f59d82ffSelric s/\/\*(.|\n)*\ca//; 119f59d82ffSelric } 120f59d82ffSelric s/^\s*//; 121f59d82ffSelric s/\s*$//; 122f59d82ffSelric s/\s+/ /g; 123603f2576Spettai if($_ =~ /\)$/){ 124f59d82ffSelric if(!/^static/ && !/^PRIVATE/){ 125f59d82ffSelric $attr = ""; 126f59d82ffSelric if(m/(.*)(__attribute__\s?\(.*\))/) { 127f59d82ffSelric $attr .= " $2"; 128f59d82ffSelric $_ = $1; 129f59d82ffSelric } 130603f2576Spettai if(m/(.*)\s(\w+DEPRECATED_FUNCTION)\s?(\(.*\))(.*)/) { 131603f2576Spettai $depfunction{$2} = 1; 132603f2576Spettai $attr .= " $2$3"; 133603f2576Spettai $_ = "$1 $4"; 134603f2576Spettai } 135603f2576Spettai if(m/(.*)\s(\w+DEPRECATED)(.*)/) { 136f59d82ffSelric $attr .= " $2"; 137603f2576Spettai $_ = "$1 $3"; 138f59d82ffSelric } 139*e0895134Schristos if(m/(.*)\s(HEIMDAL_\w+_ATTRIBUTE)\s?(\(.*\))?(.*)/) { 140*e0895134Schristos $attr .= " $2$3"; 141*e0895134Schristos $_ = "$1 $4"; 142*e0895134Schristos } 143f59d82ffSelric # remove outer () 144f59d82ffSelric s/\s*\(/</; 145f59d82ffSelric s/\)\s?$/>/; 146f59d82ffSelric # remove , within () 147f59d82ffSelric while(s/\(([^()]*),(.*)\)/($1\$$2)/g){} 148f59d82ffSelric s/\<\s*void\s*\>/<>/; 149f59d82ffSelric # remove parameter names 150f59d82ffSelric if($opt_P eq "remove") { 151f59d82ffSelric s/(\s*)([a-zA-Z0-9_]+)([,>])/$3/g; 152f59d82ffSelric s/\s+\*/*/g; 153f59d82ffSelric s/\(\*(\s*)([a-zA-Z0-9_]+)\)/(*)/g; 154f59d82ffSelric } elsif($opt_P eq "comment") { 155f59d82ffSelric s/([a-zA-Z0-9_]+)([,>])/\/\*$1\*\/$2/g; 156f59d82ffSelric s/\(\*([a-zA-Z0-9_]+)\)/(*\/\*$1\*\/)/g; 157f59d82ffSelric } 158f59d82ffSelric s/\<\>/<void>/; 159f59d82ffSelric # add newlines before parameters 160f59d82ffSelric if($flags{"multiline-proto"}) { 161f59d82ffSelric s/,\s*/,\n\t/g; 162f59d82ffSelric } else { 163f59d82ffSelric s/,\s*/, /g; 164f59d82ffSelric } 165f59d82ffSelric # fix removed , 166f59d82ffSelric s/\$/,/g; 167f59d82ffSelric # match function name 168f59d82ffSelric /([a-zA-Z0-9_]+)\s*\</; 169f59d82ffSelric $f = $1; 170f59d82ffSelric if($oproto) { 171f59d82ffSelric $LP = "__P(("; 172f59d82ffSelric $RP = "))"; 173f59d82ffSelric } else { 174f59d82ffSelric $LP = "("; 175f59d82ffSelric $RP = ")"; 176f59d82ffSelric } 177f59d82ffSelric # only add newline if more than one parameter 178f59d82ffSelric if($flags{"multiline-proto"} && /,/){ 179f59d82ffSelric s/\</ $LP\n\t/; 180f59d82ffSelric }else{ 181f59d82ffSelric s/\</ $LP/; 182f59d82ffSelric } 183f59d82ffSelric s/\>/$RP/; 184f59d82ffSelric # insert newline before function name 185f59d82ffSelric if($flags{"multiline-proto"}) { 186f59d82ffSelric s/(.*)\s([a-zA-Z0-9_]+ \Q$LP\E)/$1\n$2/; 187f59d82ffSelric } 188f59d82ffSelric if($attr ne "") { 189f59d82ffSelric $_ .= "\n $attr"; 190f59d82ffSelric } 191*e0895134Schristos if ($funcdoc) { 192*e0895134Schristos $documentation{$f} = $funcdoc; 193*e0895134Schristos } 194*e0895134Schristos $funcdoc = undef; 195*e0895134Schristos if ($apple && exists $exported{$f}) { 196*e0895134Schristos $ios = $exported{$f}{ios}; 197*e0895134Schristos $ios = "NA" if (!defined $ios); 198*e0895134Schristos $mac = $exported{$f}{macos}; 199*e0895134Schristos $mac = "NA" if (!defined $mac); 200*e0895134Schristos die "$f neither" if ($mac eq "NA" and $ios eq "NA"); 201*e0895134Schristos $_ = $_ . " __OSX_AVAILABLE_STARTING(__MAC_${mac}, __IPHONE_${ios})"; 202*e0895134Schristos } 203*e0895134Schristos if (exists $deprecated{$f}) { 204*e0895134Schristos $_ = $_ . " GSSAPI_DEPRECATED_FUNCTION(\"$deprecated{$f}\")"; 205*e0895134Schristos $depfunction{GSSAPI_DEPRECATED_FUNCTION} = 1; 206*e0895134Schristos } 207f59d82ffSelric $_ = $_ . ";"; 208f59d82ffSelric $funcs{$f} = $_; 209f59d82ffSelric } 210f59d82ffSelric } 211f59d82ffSelric $line = ""; 212f59d82ffSelric } 213f59d82ffSelric if(/\}/){ 214f59d82ffSelric $brace--; 215f59d82ffSelric } 216f59d82ffSelric if(/^\}/){ 217f59d82ffSelric $brace = 0; 218f59d82ffSelric } 219f59d82ffSelric if($brace == 0) { 220f59d82ffSelric $line = $line . " " . $_; 221f59d82ffSelric } 222f59d82ffSelric} 223f59d82ffSelric 224*e0895134Schristosdie "reached end of code and still in doxygen comment" if ($doxygen); 225*e0895134Schristosdie "reached end of code and still in comment" if ($comment); 226*e0895134Schristos 227f59d82ffSelricsub foo { 228f59d82ffSelric local ($arg) = @_; 229f59d82ffSelric $_ = $arg; 230f59d82ffSelric s/.*\/([^\/]*)/$1/; 231f59d82ffSelric s/.*\\([^\\]*)/$1/; 232f59d82ffSelric s/[^a-zA-Z0-9]/_/g; 233f59d82ffSelric "__" . $_ . "__"; 234f59d82ffSelric} 235f59d82ffSelric 236f59d82ffSelricif($opt_o) { 237603f2576Spettai open(OUT, ">${opt_o}.new"); 238f59d82ffSelric $block = &foo($opt_o); 239f59d82ffSelric} else { 240f59d82ffSelric $block = "__public_h__"; 241f59d82ffSelric} 242f59d82ffSelric 243f59d82ffSelricif($opt_p) { 244603f2576Spettai open(PRIV, ">${opt_p}.new"); 245f59d82ffSelric $private = &foo($opt_p); 246f59d82ffSelric} else { 247f59d82ffSelric $private = "__private_h__"; 248f59d82ffSelric} 249f59d82ffSelric 250f59d82ffSelric$public_h = ""; 251f59d82ffSelric$private_h = ""; 252f59d82ffSelric 253f59d82ffSelric$public_h_header .= "/* This is a generated file */ 254f59d82ffSelric#ifndef $block 255f59d82ffSelric#define $block 256*e0895134Schristos#ifndef DOXY 257f59d82ffSelric 258f59d82ffSelric"; 259f59d82ffSelricif ($oproto) { 260f59d82ffSelric $public_h_header .= "#ifdef __STDC__ 261f59d82ffSelric#include <stdarg.h> 262f59d82ffSelric#ifndef __P 263f59d82ffSelric#define __P(x) x 264f59d82ffSelric#endif 265f59d82ffSelric#else 266f59d82ffSelric#ifndef __P 267f59d82ffSelric#define __P(x) () 268f59d82ffSelric#endif 269f59d82ffSelric#endif 270f59d82ffSelric 271f59d82ffSelric"; 272f59d82ffSelric} else { 273f59d82ffSelric $public_h_header .= "#include <stdarg.h> 274f59d82ffSelric 275f59d82ffSelric"; 276f59d82ffSelric} 277f59d82ffSelric$public_h_trailer = ""; 278f59d82ffSelric 279f59d82ffSelric$private_h_header = "/* This is a generated file */ 280f59d82ffSelric#ifndef $private 281f59d82ffSelric#define $private 282f59d82ffSelric 283f59d82ffSelric"; 284f59d82ffSelricif($oproto) { 285f59d82ffSelric $private_h_header .= "#ifdef __STDC__ 286f59d82ffSelric#include <stdarg.h> 287f59d82ffSelric#ifndef __P 288f59d82ffSelric#define __P(x) x 289f59d82ffSelric#endif 290f59d82ffSelric#else 291f59d82ffSelric#ifndef __P 292f59d82ffSelric#define __P(x) () 293f59d82ffSelric#endif 294f59d82ffSelric#endif 295f59d82ffSelric 296f59d82ffSelric"; 297f59d82ffSelric} else { 298f59d82ffSelric $private_h_header .= "#include <stdarg.h> 299f59d82ffSelric 300f59d82ffSelric"; 301f59d82ffSelric} 302f59d82ffSelric$private_h_trailer = ""; 303f59d82ffSelric 304*e0895134Schristos 305f59d82ffSelricforeach(sort keys %funcs){ 306*e0895134Schristos if(/^(DllMain|main)$/) { next } 307f59d82ffSelric if ($funcs{$_} =~ /\^/) { 308f59d82ffSelric $beginblock = "#ifdef __BLOCKS__\n"; 309f59d82ffSelric $endblock = "#endif /* __BLOCKS__ */\n"; 310f59d82ffSelric } else { 311f59d82ffSelric $beginblock = $endblock = ""; 312f59d82ffSelric } 313*e0895134Schristos # if we have an export table and doesn't have content, or matches private RE 314*e0895134Schristos if((scalar(keys(%exported)) ne 0 && !exists $exported{$_} ) || /$private_func_re/) { 315*e0895134Schristos $private_h .= $beginblock; 316*e0895134Schristos# if ($apple and not /$private_func_re/) { 317*e0895134Schristos# $private_h .= "#define $_ __ApplePrivate_${_}\n"; 318*e0895134Schristos# } 319*e0895134Schristos $private_h .= $funcs{$_} . "\n" ; 320*e0895134Schristos $private_h .= $endblock . "\n"; 321f59d82ffSelric if($funcs{$_} =~ /__attribute__/) { 322f59d82ffSelric $private_attribute_seen = 1; 323f59d82ffSelric } 324f59d82ffSelric } else { 325*e0895134Schristos if($documentation{$_}) { 326*e0895134Schristos $public_h .= "/**\n"; 327*e0895134Schristos $public_h .= "$documentation{$_}"; 328*e0895134Schristos $public_h .= " */\n\n"; 329*e0895134Schristos } 330f59d82ffSelric if($flags{"function-blocking"}) { 331f59d82ffSelric $fupper = uc $_; 332f59d82ffSelric if($exported{$_} =~ /proto/) { 333f59d82ffSelric $public_h .= "#if !defined(HAVE_$fupper) || defined(NEED_${fupper}_PROTO)\n"; 334f59d82ffSelric } else { 335f59d82ffSelric $public_h .= "#ifndef HAVE_$fupper\n"; 336f59d82ffSelric } 337f59d82ffSelric } 338f59d82ffSelric $public_h .= $beginblock . $funcs{$_} . "\n" . $endblock; 339f59d82ffSelric if($funcs{$_} =~ /__attribute__/) { 340f59d82ffSelric $public_attribute_seen = 1; 341f59d82ffSelric } 342f59d82ffSelric if($flags{"function-blocking"}) { 343f59d82ffSelric $public_h .= "#endif\n"; 344f59d82ffSelric } 345f59d82ffSelric $public_h .= "\n"; 346f59d82ffSelric } 347f59d82ffSelric} 348f59d82ffSelric 349f59d82ffSelricif($flags{"gnuc-attribute"}) { 350f59d82ffSelric if ($public_attribute_seen) { 351f59d82ffSelric $public_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__) 352f59d82ffSelric#define __attribute__(x) 353f59d82ffSelric#endif 354f59d82ffSelric 355f59d82ffSelric"; 356f59d82ffSelric } 357f59d82ffSelric 358f59d82ffSelric if ($private_attribute_seen) { 359f59d82ffSelric $private_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__) 360f59d82ffSelric#define __attribute__(x) 361f59d82ffSelric#endif 362f59d82ffSelric 363f59d82ffSelric"; 364f59d82ffSelric } 365f59d82ffSelric} 366603f2576Spettai 367603f2576Spettaimy $depstr = ""; 368603f2576Spettaimy $undepstr = ""; 369603f2576Spettaiforeach (keys %depfunction) { 370603f2576Spettai $depstr .= "#ifndef $_ 371603f2576Spettai#ifndef __has_extension 372603f2576Spettai#define __has_extension(x) 0 373603f2576Spettai#define ${_}has_extension 1 374603f2576Spettai#endif 375603f2576Spettai#if __has_extension(attribute_deprecated_with_message) 376603f2576Spettai#define $_(x) __attribute__((__deprecated__(x))) 377603f2576Spettai#elif defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 ))) 378603f2576Spettai#define $_(X) __attribute__((__deprecated__)) 379603f2576Spettai#else 380603f2576Spettai#define $_(X) 381603f2576Spettai#endif 382603f2576Spettai#ifdef ${_}has_extension 383603f2576Spettai#undef __has_extension 384603f2576Spettai#undef ${_}has_extension 385603f2576Spettai#endif 386603f2576Spettai#endif /* $_ */ 387603f2576Spettai 388603f2576Spettai 389603f2576Spettai"; 390603f2576Spettai $public_h_trailer .= "#undef $_ 391603f2576Spettai 392603f2576Spettai"; 393603f2576Spettai $private_h_trailer .= "#undef $_ 394603f2576Spettai#define $_(X) 395603f2576Spettai 396603f2576Spettai"; 397603f2576Spettai} 398603f2576Spettai 399603f2576Spettai$public_h_header .= $depstr; 400603f2576Spettai$private_h_header .= $depstr; 401603f2576Spettai 402603f2576Spettai 403f59d82ffSelricif($flags{"cxx"}) { 404f59d82ffSelric $public_h_header .= "#ifdef __cplusplus 405f59d82ffSelricextern \"C\" { 406f59d82ffSelric#endif 407f59d82ffSelric 408f59d82ffSelric"; 409603f2576Spettai $public_h_trailer = "#ifdef __cplusplus 410f59d82ffSelric} 411f59d82ffSelric#endif 412f59d82ffSelric 413603f2576Spettai" . $public_h_trailer; 414f59d82ffSelric 415f59d82ffSelric} 416f59d82ffSelricif ($opt_E) { 417f59d82ffSelric $public_h_header .= "#ifndef $opt_E 418f59d82ffSelric#ifndef ${opt_E}_FUNCTION 419f59d82ffSelric#if defined(_WIN32) 420f59d82ffSelric#define ${opt_E}_FUNCTION __declspec(dllimport) 421f59d82ffSelric#define ${opt_E}_CALL __stdcall 422f59d82ffSelric#define ${opt_E}_VARIABLE __declspec(dllimport) 423f59d82ffSelric#else 424f59d82ffSelric#define ${opt_E}_FUNCTION 425f59d82ffSelric#define ${opt_E}_CALL 426f59d82ffSelric#define ${opt_E}_VARIABLE 427f59d82ffSelric#endif 428f59d82ffSelric#endif 429f59d82ffSelric#endif 430f59d82ffSelric"; 431f59d82ffSelric 432f59d82ffSelric $private_h_header .= "#ifndef $opt_E 433f59d82ffSelric#ifndef ${opt_E}_FUNCTION 434f59d82ffSelric#if defined(_WIN32) 435f59d82ffSelric#define ${opt_E}_FUNCTION __declspec(dllimport) 436f59d82ffSelric#define ${opt_E}_CALL __stdcall 437f59d82ffSelric#define ${opt_E}_VARIABLE __declspec(dllimport) 438f59d82ffSelric#else 439f59d82ffSelric#define ${opt_E}_FUNCTION 440f59d82ffSelric#define ${opt_E}_CALL 441f59d82ffSelric#define ${opt_E}_VARIABLE 442f59d82ffSelric#endif 443f59d82ffSelric#endif 444f59d82ffSelric#endif 445f59d82ffSelric 446f59d82ffSelric"; 447f59d82ffSelric} 448f59d82ffSelric 449603f2576Spettai$public_h_trailer .= $undepstr; 450603f2576Spettai$private_h_trailer .= $undepstr; 451603f2576Spettai 452f59d82ffSelricif ($public_h ne "" && $flags{"header"}) { 453f59d82ffSelric $public_h = $public_h_header . $public_h . 454*e0895134Schristos $public_h_trailer . "#endif /* DOXY */\n#endif /* $block */\n"; 455f59d82ffSelric} 456f59d82ffSelricif ($private_h ne "" && $flags{"header"}) { 457f59d82ffSelric $private_h = $private_h_header . $private_h . 458f59d82ffSelric $private_h_trailer . "#endif /* $private */\n"; 459f59d82ffSelric} 460f59d82ffSelric 461f59d82ffSelricif($opt_o) { 462f59d82ffSelric print OUT $public_h; 463f59d82ffSelric} 464f59d82ffSelricif($opt_p) { 465f59d82ffSelric print PRIV $private_h; 466f59d82ffSelric} 467f59d82ffSelric 468f59d82ffSelricclose OUT; 469f59d82ffSelricclose PRIV; 470603f2576Spettai 471603f2576Spettaiif ($opt_o) { 472603f2576Spettai 473603f2576Spettai if (compare("${opt_o}.new", ${opt_o}) != 0) { 474603f2576Spettai printf("updating ${opt_o}\n"); 475603f2576Spettai rename("${opt_o}.new", ${opt_o}); 476603f2576Spettai } else { 477603f2576Spettai unlink("${opt_o}.new"); 478603f2576Spettai } 479603f2576Spettai} 480603f2576Spettai 481603f2576Spettaiif ($opt_p) { 482603f2576Spettai if (compare("${opt_p}.new", ${opt_p}) != 0) { 483603f2576Spettai printf("updating ${opt_p}\n"); 484603f2576Spettai rename("${opt_p}.new", ${opt_p}); 485603f2576Spettai } else { 486603f2576Spettai unlink("${opt_p}.new"); 487603f2576Spettai } 488603f2576Spettai} 489