gss: port NegoEx implementation from MIT
[heimdal.git] / cf / make-proto.pl
blob36a040ce6c0a8d6d6bbe9d2fe0e9964088430e00
1 # Make prototypes from .c files
2 # $Id$
4 use Getopt::Std;
5 use File::Compare;
7 use JSON;
9 my $comment = 0;
10 my $doxygen = 0;
11 my $funcdoc = 0;
12 my $if_0 = 0;
13 my $brace = 0;
14 my $line = "";
15 my $debug = 0;
16 my $oproto = 1;
17 my $private_func_re = "^_";
18 my %depfunction;
19 my %exported;
20 my %deprecated;
21 my $apple = 0;
22 my %documentation;
24 getopts('x:m:o:p:dqE:R:P:') || die "foo";
25 if($opt_a) {
26 $apple = 1;
29 if($opt_a) {
30 $apple = 1;
33 if($opt_d) {
34 $debug = 1;
37 if($opt_q) {
38 $oproto = 0;
41 if($opt_R) {
42 $private_func_re = $opt_R;
44 my %flags = (
45 'multiline-proto' => 1,
46 'header' => 1,
47 'function-blocking' => 0,
48 'gnuc-attribute' => 1,
49 'cxx' => 1
51 if($opt_m) {
52 foreach $i (split(/,/, $opt_m)) {
53 if($i eq "roken") {
54 $flags{"multiline-proto"} = 0;
55 $flags{"header"} = 0;
56 $flags{"function-blocking"} = 0;
57 $flags{"gnuc-attribute"} = 0;
58 $flags{"cxx"} = 0;
59 } else {
60 if(substr($i, 0, 3) eq "no-") {
61 $flags{substr($i, 3)} = 0;
62 } else {
63 $flags{$i} = 1;
69 if($opt_x) {
70 my $EXP;
71 local $/;
72 open(EXP, '<', $opt_x) || die "open ${opt_x}";
73 my $obj = JSON->new->utf8->decode(<EXP>);
74 close $EXP;
76 foreach my $x (keys %$obj) {
77 if (defined $obj->{$x}->{"export"}) {
78 $exported{$x} = $obj->{$x};
80 if (defined $obj->{$x}->{"deprecated"}) {
81 $deprecated{$x} = $obj->{$x}->{"deprecated"};
86 while(<>) {
87 print $brace, " ", $_ if($debug);
89 # Handle C comments
90 s@/\*.*\*/@@;
91 s@//.*/@@;
92 if ( s@/\*\*(.*)@@) { $comment = 1; $doxygen = 1; $funcdoc = $1;
93 } elsif ( s@/\*.*@@) { $comment = 1;
94 } elsif ($comment && s@.*\*/@@) { $comment = 0; $doxygen = 0;
95 } elsif ($doxygen) { $funcdoc .= $_; next;
96 } elsif ($comment) { next; }
98 # Handle CPP #define's
99 $define = 1 if /^\s*\#\s*define/;
100 if ($define) {
101 $define = 0 if ! /\\$/;
102 next;
105 if(/^\#if 0/) {
106 $if_0 = 1;
108 if($if_0 && /^\#endif/) {
109 $if_0 = 0;
111 if($if_0) { next }
112 if(/^\s*\#/) {
113 next;
115 if(/^\s*$/) {
116 $line = "";
117 next;
119 if(/\{/){
120 if (!/\}/) {
121 $brace++;
123 $_ = $line;
124 while(s/\*\//\ca/){
125 s/\/\*(.|\n)*\ca//;
127 s/^\s*//;
128 s/\s*$//;
129 s/\s+/ /g;
130 if($_ =~ /\)$/){
131 if(!/^static/ && !/^PRIVATE/){
132 $attr = "";
133 if(m/(.*)(__attribute__\s?\(.*\))/) {
134 $attr .= " $2";
135 $_ = $1;
137 if(m/(.*)\s(\w+DEPRECATED_FUNCTION)\s?(\(.*\))(.*)/) {
138 $depfunction{$2} = 1;
139 $attr .= " $2$3";
140 $_ = "$1 $4";
142 if(m/(.*)\s(\w+DEPRECATED)(.*)/) {
143 $attr .= " $2";
144 $_ = "$1 $3";
146 if(m/(.*)\s(HEIMDAL_\w+_ATTRIBUTE)\s?(\(.*\))?(.*)/) {
147 $attr .= " $2$3";
148 $_ = "$1 $4";
150 # remove outer ()
151 s/\s*\(/</;
152 s/\)\s?$/>/;
153 # remove , within ()
154 while(s/\(([^()]*),(.*)\)/($1\$$2)/g){}
155 s/\<\s*void\s*\>/<>/;
156 # remove parameter names
157 if($opt_P eq "remove") {
158 s/(\s*)([a-zA-Z0-9_]+)([,>])/$3/g;
159 s/\s+\*/*/g;
160 s/\(\*(\s*)([a-zA-Z0-9_]+)\)/(*)/g;
161 } elsif($opt_P eq "comment") {
162 s/([a-zA-Z0-9_]+)([,>])/\/\*$1\*\/$2/g;
163 s/\(\*([a-zA-Z0-9_]+)\)/(*\/\*$1\*\/)/g;
165 s/\<\>/<void>/;
166 # add newlines before parameters
167 if($flags{"multiline-proto"}) {
168 s/,\s*/,\n\t/g;
169 } else {
170 s/,\s*/, /g;
172 # fix removed ,
173 s/\$/,/g;
174 # match function name
175 /([a-zA-Z0-9_]+)\s*\</;
176 $f = $1;
177 if($oproto) {
178 $LP = "__P((";
179 $RP = "))";
180 } else {
181 $LP = "(";
182 $RP = ")";
184 # only add newline if more than one parameter
185 if($flags{"multiline-proto"} && /,/){
186 s/\</ $LP\n\t/;
187 }else{
188 s/\</ $LP/;
190 s/\>/$RP/;
191 # insert newline before function name
192 if($flags{"multiline-proto"}) {
193 s/(.*)\s([a-zA-Z0-9_]+ \Q$LP\E)/$1\n$2/;
195 if($attr ne "") {
196 $_ .= "\n $attr";
198 if ($funcdoc) {
199 $documentation{$f} = $funcdoc;
201 $funcdoc = undef;
202 if ($apple && exists $exported{$f}) {
203 $ios = $exported{$f}{ios};
204 $ios = "NA" if (!defined $ios);
205 $mac = $exported{$f}{macos};
206 $mac = "NA" if (!defined $mac);
207 die "$f neither" if ($mac eq "NA" and $ios eq "NA");
208 $_ = $_ . " __OSX_AVAILABLE_STARTING(__MAC_${mac}, __IPHONE_${ios})";
210 if (exists $deprecated{$f}) {
211 $_ = $_ . " GSSAPI_DEPRECATED_FUNCTION(\"$deprecated{$f}\")";
212 $depfunction{GSSAPI_DEPRECATED_FUNCTION} = 1;
214 $_ = $_ . ";";
215 $funcs{$f} = $_;
218 $line = "";
220 if(/\}/){
221 $brace--;
223 if(/^\}/){
224 $brace = 0;
226 if($brace == 0) {
227 $line = $line . " " . $_;
231 die "reached end of code and still in doxygen comment" if ($doxygen);
232 die "reached end of code and still in comment" if ($comment);
234 sub foo {
235 local ($arg) = @_;
236 $_ = $arg;
237 s/.*\/([^\/]*)/$1/;
238 s/.*\\([^\\]*)/$1/;
239 s/[^a-zA-Z0-9]/_/g;
240 "__" . $_ . "__";
243 if($opt_o) {
244 open(OUT, ">${opt_o}.new");
245 $block = &foo($opt_o);
246 } else {
247 $block = "__public_h__";
250 if($opt_p) {
251 open(PRIV, ">${opt_p}.new");
252 $private = &foo($opt_p);
253 } else {
254 $private = "__private_h__";
257 $public_h = "";
258 $private_h = "";
260 $public_h_header .= "/* This is a generated file */
261 #ifndef $block
262 #define $block
263 #ifndef DOXY
266 if ($oproto) {
267 $public_h_header .= "#ifdef __STDC__
268 #include <stdarg.h>
269 #ifndef __P
270 #define __P(x) x
271 #endif
272 #else
273 #ifndef __P
274 #define __P(x) ()
275 #endif
276 #endif
279 } else {
280 $public_h_header .= "#include <stdarg.h>
284 $public_h_trailer = "";
286 $private_h_header = "/* This is a generated file */
287 #ifndef $private
288 #define $private
291 if($oproto) {
292 $private_h_header .= "#ifdef __STDC__
293 #include <stdarg.h>
294 #ifndef __P
295 #define __P(x) x
296 #endif
297 #else
298 #ifndef __P
299 #define __P(x) ()
300 #endif
301 #endif
304 } else {
305 $private_h_header .= "#include <stdarg.h>
309 $private_h_trailer = "";
312 foreach(sort keys %funcs){
313 if(/^(DllMain|main)$/) { next }
314 if ($funcs{$_} =~ /\^/) {
315 $beginblock = "#ifdef __BLOCKS__\n";
316 $endblock = "#endif /* __BLOCKS__ */\n";
317 } else {
318 $beginblock = $endblock = "";
320 # if we have an export table and doesn't have content, or matches private RE
321 if((scalar(keys(%exported)) ne 0 && !exists $exported{$_} ) || /$private_func_re/) {
322 $private_h .= $beginblock;
323 # if ($apple and not /$private_func_re/) {
324 # $private_h .= "#define $_ __ApplePrivate_${_}\n";
326 $private_h .= $funcs{$_} . "\n" ;
327 $private_h .= $endblock . "\n";
328 if($funcs{$_} =~ /__attribute__/) {
329 $private_attribute_seen = 1;
331 } else {
332 if($documentation{$_}) {
333 $public_h .= "/**\n";
334 $public_h .= "$documentation{$_}";
335 $public_h .= " */\n\n";
337 if($flags{"function-blocking"}) {
338 $fupper = uc $_;
339 if($exported{$_} =~ /proto/) {
340 $public_h .= "#if !defined(HAVE_$fupper) || defined(NEED_${fupper}_PROTO)\n";
341 } else {
342 $public_h .= "#ifndef HAVE_$fupper\n";
345 $public_h .= $beginblock . $funcs{$_} . "\n" . $endblock;
346 if($funcs{$_} =~ /__attribute__/) {
347 $public_attribute_seen = 1;
349 if($flags{"function-blocking"}) {
350 $public_h .= "#endif\n";
352 $public_h .= "\n";
356 if($flags{"gnuc-attribute"}) {
357 if ($public_attribute_seen) {
358 $public_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
359 #define __attribute__(x)
360 #endif
365 if ($private_attribute_seen) {
366 $private_h_header .= "#if !defined(__GNUC__) && !defined(__attribute__)
367 #define __attribute__(x)
368 #endif
374 my $depstr = "";
375 my $undepstr = "";
376 foreach (keys %depfunction) {
377 $depstr .= "#ifndef $_
378 #ifndef __has_extension
379 #define __has_extension(x) 0
380 #define ${_}has_extension 1
381 #endif
382 #if __has_extension(attribute_deprecated_with_message)
383 #define $_(x) __attribute__((__deprecated__(x)))
384 #elif defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))
385 #define $_(X) __attribute__((__deprecated__))
386 #else
387 #define $_(X)
388 #endif
389 #ifdef ${_}has_extension
390 #undef __has_extension
391 #undef ${_}has_extension
392 #endif
393 #endif /* $_ */
397 $public_h_trailer .= "#undef $_
400 $private_h_trailer .= "#undef $_
401 #define $_(X)
406 $public_h_header .= $depstr;
407 $private_h_header .= $depstr;
410 if($flags{"cxx"}) {
411 $public_h_header .= "#ifdef __cplusplus
412 extern \"C\" {
413 #endif
416 $public_h_trailer = "#ifdef __cplusplus
418 #endif
420 " . $public_h_trailer;
423 if ($opt_E) {
424 $public_h_header .= "#ifndef $opt_E
425 #ifndef ${opt_E}_FUNCTION
426 #if defined(_WIN32)
427 #define ${opt_E}_FUNCTION __declspec(dllimport)
428 #else
429 #define ${opt_E}_FUNCTION
430 #endif
431 #endif
432 #ifndef ${opt_E}_NORETURN_FUNCTION
433 #if defined(_WIN32)
434 #define ${opt_E}_NORETURN_FUNCTION __declspec(dllimport noreturn)
435 #else
436 #define ${opt_E}_NORETURN_FUNCTION
437 #endif
438 #endif
439 #ifndef ${opt_E}_CALL
440 #if defined(_WIN32)
441 #define ${opt_E}_CALL __stdcall
442 #else
443 #define ${opt_E}_CALL
444 #endif
445 #endif
446 #ifndef ${opt_E}_VARIABLE
447 #if defined(_WIN32)
448 #define ${opt_E}_VARIABLE __declspec(dllimport)
449 #else
450 #define ${opt_E}_VARIABLE
451 #endif
452 #endif
453 #endif
456 $private_h_header .= "#ifndef $opt_E
457 #ifndef ${opt_E}_FUNCTION
458 #if defined(_WIN32)
459 #define ${opt_E}_FUNCTION __declspec(dllimport)
460 #else
461 #define ${opt_E}_FUNCTION
462 #endif
463 #endif
464 #ifndef ${opt_E}_NORETURN_FUNCTION
465 #if defined(_WIN32)
466 #define ${opt_E}_NORETURN_FUNCTION __declspec(dllimport noreturn)
467 #else
468 #define ${opt_E}_NORETURN_FUNCTION
469 #endif
470 #endif
471 #ifndef ${opt_E}_CALL
472 #if defined(_WIN32)
473 #define ${opt_E}_CALL __stdcall
474 #else
475 #define ${opt_E}_CALL
476 #endif
477 #endif
478 #ifndef ${opt_E}_VARIABLE
479 #if defined(_WIN32)
480 #define ${opt_E}_VARIABLE __declspec(dllimport)
481 #else
482 #define ${opt_E}_VARIABLE
483 #endif
484 #endif
485 #endif
489 $public_h_trailer .= $undepstr;
490 $private_h_trailer .= $undepstr;
492 if ($public_h ne "" && $flags{"header"}) {
493 $public_h = $public_h_header . $public_h .
494 $public_h_trailer . "#endif /* DOXY */\n#endif /* $block */\n";
496 if ($private_h ne "" && $flags{"header"}) {
497 $private_h = $private_h_header . $private_h .
498 $private_h_trailer . "#endif /* $private */\n";
501 if($opt_o) {
502 print OUT $public_h;
504 if($opt_p) {
505 print PRIV $private_h;
508 close OUT;
509 close PRIV;
511 if ($opt_o) {
513 if (compare("${opt_o}.new", ${opt_o}) != 0) {
514 printf("updating ${opt_o}\n");
515 rename("${opt_o}.new", ${opt_o});
516 } else {
517 unlink("${opt_o}.new");
521 if ($opt_p) {
522 if (compare("${opt_p}.new", ${opt_p}) != 0) {
523 printf("updating ${opt_p}\n");
524 rename("${opt_p}.new", ${opt_p});
525 } else {
526 unlink("${opt_p}.new");