1# Make prototypes from .c files 2# Id 3 4use Getopt::Std; 5use File::Compare; 6 7my $comment = 0; 8my $if_0 = 0; 9my $brace = 0; 10my $line = ""; 11my $debug = 0; 12my $oproto = 1; 13my $private_func_re = "^_"; 14my %depfunction = (); 15 16getopts('x:m:o:p:dqE:R:P:') || die "foo"; 17 18if($opt_d) { 19 $debug = 1; 20} 21 22if($opt_q) { 23 $oproto = 0; 24} 25 26if($opt_R) { 27 $private_func_re = $opt_R; 28} 29my %flags = ( 30 'multiline-proto' => 1, 31 'header' => 1, 32 'function-blocking' => 0, 33 'gnuc-attribute' => 1, 34 'cxx' => 1 35 ); 36if($opt_m) { 37 foreach $i (split(/,/, $opt_m)) { 38 if($i eq "roken") { 39 $flags{"multiline-proto"} = 0; 40 $flags{"header"} = 0; 41 $flags{"function-blocking"} = 0; 42 $flags{"gnuc-attribute"} = 0; 43 $flags{"cxx"} = 0; 44 } else { 45 if(substr($i, 0, 3) eq "no-") { 46 $flags{substr($i, 3)} = 0; 47 } else { 48 $flags{$i} = 1; 49 } 50 } 51 } 52} 53 54if($opt_x) { 55 open(EXP, $opt_x); 56 while(<EXP>) { 57 chomp; 58 s/\#.*//g; 59 s/\s+/ /g; 60 if(/^([a-zA-Z0-9_]+)\s?(.*)$/) { 61 $exported{$1} = $2; 62 } else { 63 print $_, "\n"; 64 } 65 } 66 close EXP; 67} 68 69while(<>) { 70 print $brace, " ", $_ if($debug); 71 72 # Handle C comments 73 s@/\*.*\*/@@; 74 s@//.*/@@; 75 if ( s@/\*.*@@) { $comment = 1; 76 } elsif ($comment && s@.*\*/@@) { $comment = 0; 77 } elsif ($comment) { next; } 78 79 if(/^\#if 0/) { 80 $if_0 = 1; 81 } 82 if($if_0 && /^\#endif/) { 83 $if_0 = 0; 84 } 85 if($if_0) { next } 86 if(/^\s*\#/) { 87 next; 88 } 89 if(/^\s*$/) { 90 $line = ""; 91 next; 92 } 93 if(/\{/){ 94 if (!/\}/) { 95 $brace++; 96 } 97 $_ = $line; 98 while(s/\*\//\ca/){ 99 s/\/\*(.|\n)*\ca//; 100 } 101 s/^\s*//; 102 s/\s*$//; 103 s/\s+/ /g; 104 if($_ =~ /\)$/){ 105 if(!/^static/ && !/^PRIVATE/){ 106 $attr = ""; 107 if(m/(.*)(__attribute__\s?\(.*\))/) { 108 $attr .= " $2"; 109 $_ = $1; 110 } 111 if(m/(.*)\s(\w+DEPRECATED_FUNCTION)\s?(\(.*\))(.*)/) { 112 $depfunction{$2} = 1; 113 $attr .= " $2$3"; 114 $_ = "$1 $4"; 115 } 116 if(m/(.*)\s(\w+DEPRECATED)(.*)/) { 117 $attr .= " $2"; 118 $_ = "$1 $3"; 119 } 120 # remove outer () 121 s/\s*\(/</; 122 s/\)\s?$/>/; 123 # remove , within () 124 while(s/\(([^()]*),(.*)\)/($1\$$2)/g){} 125 s/\<\s*void\s*\>/<>/; 126 # remove parameter names 127 if($opt_P eq "remove") { 128 s/(\s*)([a-zA-Z0-9_]+)([,>])/$3/g; 129 s/\s+\*/*/g; 130 s/\(\*(\s*)([a-zA-Z0-9_]+)\)/(*)/g; 131 } elsif($opt_P eq "comment") { 132 s/([a-zA-Z0-9_]+)([,>])/\/\*$1\*\/$2/g; 133 s/\(\*([a-zA-Z0-9_]+)\)/(*\/\*$1\*\/)/g; 134 } 135 s/\<\>/<void>/; 136 # add newlines before parameters 137 if($flags{"multiline-proto"}) { 138 s/,\s*/,\n\t/g; 139 } else { 140 s/,\s*/, /g; 141 } 142 # fix removed , 143 s/\$/,/g; 144 # match function name 145 /([a-zA-Z0-9_]+)\s*\</; 146 $f = $1; 147 if($oproto) { 148 $LP = "__P(("; 149 $RP = "))"; 150 } else { 151 $LP = "("; 152 $RP = ")"; 153 } 154 # only add newline if more than one parameter 155 if($flags{"multiline-proto"} && /,/){ 156 s/\</ $LP\n\t/; 157 }else{ 158 s/\</ $LP/; 159 } 160 s/\>/$RP/; 161 # insert newline before function name 162 if($flags{"multiline-proto"}) { 163 s/(.*)\s([a-zA-Z0-9_]+ \Q$LP\E)/$1\n$2/; 164 } 165 if($attr ne "") { 166 $_ .= "\n $attr"; 167 } 168 $_ = $_ . ";"; 169 $funcs{$f} = $_; 170 } 171 } 172 $line = ""; 173 } 174 if(/\}/){ 175 $brace--; 176 } 177 if(/^\}/){ 178 $brace = 0; 179 } 180 if($brace == 0) { 181 $line = $line . " " . $_; 182 } 183} 184 185sub foo { 186 local ($arg) = @_; 187 $_ = $arg; 188 s/.*\/([^\/]*)/$1/; 189 s/.*\\([^\\]*)/$1/; 190 s/[^a-zA-Z0-9]/_/g; 191 "__" . $_ . "__"; 192} 193 194if($opt_o) { 195 open(OUT, ">${opt_o}.new"); 196 $block = &foo($opt_o); 197} else { 198 $block = "__public_h__"; 199} 200 201if($opt_p) { 202 open(PRIV, ">${opt_p}.new"); 203 $private = &foo($opt_p); 204} else { 205 $private = "__private_h__"; 206} 207 208$public_h = ""; 209$private_h = ""; 210 211$public_h_header .= "/* This is a generated file */ 212#ifndef $block 213#define $block 214 215"; 216if ($oproto) { 217 $public_h_header .= "#ifdef __STDC__ 218#include <stdarg.h> 219#ifndef __P 220#define __P(x) x 221#endif 222#else 223#ifndef __P 224#define __P(x) () 225#endif 226#endif 227 228"; 229} else { 230 $public_h_header .= "#include <stdarg.h> 231 232"; 233} 234$public_h_trailer = ""; 235 236$private_h_header = "/* This is a generated file */ 237#ifndef $private 238#define $private 239 240"; 241if($oproto) { 242 $private_h_header .= "#ifdef __STDC__ 243#include <stdarg.h> 244#ifndef __P 245#define __P(x) x 246#endif 247#else 248#ifndef __P 249#define __P(x) () 250#endif 251#endif 252 253"; 254} else { 255 $private_h_header .= "#include <stdarg.h> 256 257"; 258} 259$private_h_trailer = ""; 260 261foreach(sort keys %funcs){ 262 if(/^(main)$/) { next } 263 if ($funcs{$_} =~ /\^/) { 264 $beginblock = "#ifdef __BLOCKS__\n"; 265 $endblock = "#endif /* __BLOCKS__ */\n"; 266 } else { 267 $beginblock = $endblock = ""; 268 } 269 if(!defined($exported{$_}) && /$private_func_re/) { 270 $private_h .= $beginblock . $funcs{$_} . "\n" . $endblock . "\n"; 271 if($funcs{$_} =~ /__attribute__/) { 272 $private_attribute_seen = 1; 273 } 274 } else { 275 if($flags{"function-blocking"}) { 276 $fupper = uc $_; 277 if($exported{$_} =~ /proto/) { 278 $public_h .= "#if !defined(HAVE_$fupper) || defined(NEED_${fupper}_PROTO)\n"; 279 } else { 280 $public_h .= "#ifndef HAVE_$fupper\n"; 281 } 282 } 283 $public_h .= $beginblock . $funcs{$_} . "\n" . $endblock; 284 if($funcs{$_} =~ /__attribute__/) { 285 $public_attribute_seen = 1; 286 } 287 if($flags{"function-blocking"}) { 288 $public_h .= "#endif\n"; 289 } 290 $public_h .= "\n"; 291 } 292} 293 294if($flags{"gnuc-attribute"}) { 295 if ($public_attribute_seen) { 296 $public_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__) 297#define __attribute__(x) 298#endif 299 300"; 301 } 302 303 if ($private_attribute_seen) { 304 $private_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__) 305#define __attribute__(x) 306#endif 307 308"; 309 } 310} 311 312my $depstr = ""; 313my $undepstr = ""; 314foreach (keys %depfunction) { 315 $depstr .= "#ifndef $_ 316#ifndef __has_extension 317#define __has_extension(x) 0 318#define ${_}has_extension 1 319#endif 320#if __has_extension(attribute_deprecated_with_message) 321#define $_(x) __attribute__((__deprecated__(x))) 322#elif defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 ))) 323#define $_(X) __attribute__((__deprecated__)) 324#else 325#define $_(X) 326#endif 327#ifdef ${_}has_extension 328#undef __has_extension 329#undef ${_}has_extension 330#endif 331#endif /* $_ */ 332 333 334"; 335 $public_h_trailer .= "#undef $_ 336 337"; 338 $private_h_trailer .= "#undef $_ 339#define $_(X) 340 341"; 342} 343 344$public_h_header .= $depstr; 345$private_h_header .= $depstr; 346 347 348if($flags{"cxx"}) { 349 $public_h_header .= "#ifdef __cplusplus 350extern \"C\" { 351#endif 352 353"; 354 $public_h_trailer = "#ifdef __cplusplus 355} 356#endif 357 358" . $public_h_trailer; 359 360} 361if ($opt_E) { 362 $public_h_header .= "#ifndef $opt_E 363#ifndef ${opt_E}_FUNCTION 364#if defined(_WIN32) 365#define ${opt_E}_FUNCTION __declspec(dllimport) 366#define ${opt_E}_CALL __stdcall 367#define ${opt_E}_VARIABLE __declspec(dllimport) 368#else 369#define ${opt_E}_FUNCTION 370#define ${opt_E}_CALL 371#define ${opt_E}_VARIABLE 372#endif 373#endif 374#endif 375"; 376 377 $private_h_header .= "#ifndef $opt_E 378#ifndef ${opt_E}_FUNCTION 379#if defined(_WIN32) 380#define ${opt_E}_FUNCTION __declspec(dllimport) 381#define ${opt_E}_CALL __stdcall 382#define ${opt_E}_VARIABLE __declspec(dllimport) 383#else 384#define ${opt_E}_FUNCTION 385#define ${opt_E}_CALL 386#define ${opt_E}_VARIABLE 387#endif 388#endif 389#endif 390 391"; 392} 393 394$public_h_trailer .= $undepstr; 395$private_h_trailer .= $undepstr; 396 397if ($public_h ne "" && $flags{"header"}) { 398 $public_h = $public_h_header . $public_h . 399 $public_h_trailer . "#endif /* $block */\n"; 400} 401if ($private_h ne "" && $flags{"header"}) { 402 $private_h = $private_h_header . $private_h . 403 $private_h_trailer . "#endif /* $private */\n"; 404} 405 406if($opt_o) { 407 print OUT $public_h; 408} 409if($opt_p) { 410 print PRIV $private_h; 411} 412 413close OUT; 414close PRIV; 415 416if ($opt_o) { 417 418 if (compare("${opt_o}.new", ${opt_o}) != 0) { 419 printf("updating ${opt_o}\n"); 420 rename("${opt_o}.new", ${opt_o}); 421 } else { 422 unlink("${opt_o}.new"); 423 } 424} 425 426if ($opt_p) { 427 if (compare("${opt_p}.new", ${opt_p}) != 0) { 428 printf("updating ${opt_p}\n"); 429 rename("${opt_p}.new", ${opt_p}); 430 } else { 431 unlink("${opt_p}.new"); 432 } 433} 434