|
3 | 3 | use warnings;
|
4 | 4 | use File::Basename;
|
5 | 5 |
|
| 6 | +# TODO add contexts for |
| 7 | +# "multiline function signatures" |
| 8 | +# docustrings for QgsFeature::QgsAttributes |
| 9 | + |
6 | 10 | my $headerfile = $ARGV[0];
|
7 | 11 |
|
8 | 12 | open(my $header, "<", $headerfile) || die "Couldn't open '".$headerfile."' for reading because: ".$!;
|
9 | 13 |
|
10 |
| -my $GLOBAL = 1; |
11 |
| -my $DOXYGEN_BLOCK = 2; |
| 14 | +# contexts |
| 15 | +my $SIP_RUN = 0; |
| 16 | +my $HEADER_CODE = 0; |
| 17 | +my $PRIVATE_SECTION = 0; |
12 | 18 |
|
13 |
| -# TODO add contexts for |
14 |
| -# "private: " -> skip |
15 |
| -# "function bodies" -> skip |
16 |
| -# "multiline function signatures" |
17 |
| -# "enums" -> remove assigned values |
18 |
| - |
19 |
| -my $context = $GLOBAL; |
20 | 19 | my $comment;
|
| 20 | +my $nesting_index = 0; |
| 21 | +my $private_section_line = ''; |
| 22 | + |
| 23 | + |
| 24 | +print "/******************************************************************\n"; |
| 25 | +print " * This file has been generated automatically by sipify.pl *\n"; |
| 26 | +print " * Do not edit manually ! Edit header file and generate it again. *\n"; |
| 27 | +print " *****************************************************************/\n"; |
| 28 | + |
21 | 29 |
|
22 | 30 | while(!eof $header) {
|
23 | 31 | my $line = readline $header;
|
| 32 | + #print $line; |
24 | 33 |
|
25 | 34 | # Skip preprocessor stuff
|
26 |
| - if ($line =~ /^\s*#/) { |
27 |
| - if ($line !~ /NO_SIPIFY/) { |
| 35 | + if ($line =~ m/^\s*#/) { |
| 36 | + if ( $line =~ m/^\s*#ifdef SIP_RUN/) { |
| 37 | + |
| 38 | + $SIP_RUN = 1; |
| 39 | + if ($PRIVATE_SECTION == 1) { |
| 40 | + print $private_section_line; |
| 41 | + } |
| 42 | + next; |
| 43 | + } |
| 44 | + if ( $SIP_RUN == 1 ) { |
| 45 | + if ( $line =~ m/^\s*#endif/ ) { |
| 46 | + if ( $nesting_index == 0 ){ |
| 47 | + $SIP_RUN = 0; |
| 48 | + next; |
| 49 | + } |
| 50 | + else { |
| 51 | + $nesting_index--; |
| 52 | + } |
| 53 | + } |
| 54 | + if ( $line =~ m/^\s*#if(def)?\s+/ ) { |
| 55 | + $nesting_index++; |
| 56 | + } |
| 57 | + |
| 58 | + # if there is an else at this level, code will be ignored i.e. not SIP_RUN |
| 59 | + if ( $line =~ m/^\s*#else/ && $nesting_index == 0) { |
| 60 | + while(!eof $header) { |
| 61 | + $line = readline $header; |
| 62 | + if ( $line =~ m/^\s*#if(def)?\s+/ ) { |
| 63 | + $nesting_index++; |
| 64 | + } |
| 65 | + elsif ( $line =~ m/^\s*#endif/ ) { |
| 66 | + if ( $nesting_index == 0 ) { |
| 67 | + $SIP_RUN = 0; |
| 68 | + last; |
| 69 | + } |
| 70 | + else { |
| 71 | + $nesting_index--; |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | + next; |
| 76 | + } |
| 77 | + } |
| 78 | + elsif ( $line =~ m/^\s*#ifndef SIP_RUN/) { |
| 79 | + # code is ignored here |
| 80 | + while(!eof $header) { |
| 81 | + $line = readline $header; |
| 82 | + if ( $line =~ m/^\s*#if(def)?\s+/ ) { |
| 83 | + $nesting_index++; |
| 84 | + } |
| 85 | + elsif ( $line =~ m/^\s*#else/ && $nesting_index == 0 ) { |
| 86 | + # code here will be printed out |
| 87 | + if ($PRIVATE_SECTION == 1) { |
| 88 | + print $private_section_line; |
| 89 | + } |
| 90 | + $SIP_RUN = 1; |
| 91 | + last; |
| 92 | + } |
| 93 | + elsif ( $line =~ m/^\s*#endif/ ) { |
| 94 | + if ( $nesting_index == 0 ) { |
| 95 | + $SIP_RUN = 0; |
| 96 | + last; |
| 97 | + } |
| 98 | + else { |
| 99 | + $nesting_index--; |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | + next; |
| 104 | + } |
| 105 | + else { |
28 | 106 | next;
|
29 | 107 | }
|
30 | 108 | }
|
| 109 | + |
| 110 | + # TYPE HEADER CODE |
| 111 | + if ( $HEADER_CODE && $SIP_RUN == 0 ) { |
| 112 | + $HEADER_CODE = 0; |
| 113 | + print "%End\n"; |
| 114 | + } |
| 115 | + |
31 | 116 | # Skip forward declarations
|
32 | 117 | if ($line =~ m/^\s*class \w+;$/) {
|
33 | 118 | next;
|
34 | 119 | }
|
35 | 120 | # Skip Q_OBJECT, Q_PROPERTY, Q_ENUM, Q_GADGET
|
36 |
| - if ($line =~ m/^\s*Q_(OBJECT|ENUMS|PROPERTY|GADGET).*?$/) { |
| 121 | + if ($line =~ m/^\s*Q_(OBJECT|ENUMS|PROPERTY|GADGET|DECLARE_METATYPE).*?$/) { |
37 | 122 | next;
|
38 | 123 | }
|
39 | 124 |
|
40 |
| - # Doxygen comment started |
41 |
| - if ($DOXYGEN_BLOCK != $context) { |
42 |
| - if ($line =~ m/\s*\/\*\*/) { |
43 |
| - $context = $DOXYGEN_BLOCK; |
44 |
| - $comment = ""; |
45 |
| - } |
46 |
| - # class declaration started |
47 |
| - if ($line =~ m/^(\s*class)\s*([A-Z]+_EXPORT)(\s+\w+)(\s*\:.*)?$/) { |
48 |
| - $line = "$1$3"; |
49 |
| - # Inheritance |
50 |
| - if ($4) { |
51 |
| - my $m; |
52 |
| - $m = $4; |
53 |
| - $m =~ s/public //g; |
54 |
| - $m =~ s/\s?private \w+,?//; |
55 |
| - $line .= $m; |
| 125 | + # SIP_SKIP |
| 126 | + if ( $line =~ m/SIP_SKIP/ ) { |
| 127 | + $line =~ s/^(\s*)(\w.*)$/$1\/\/ $2\n/; |
| 128 | + print $line; |
| 129 | + next; |
| 130 | + } |
| 131 | + |
| 132 | + # Detect comment block |
| 133 | + if ($line =~ m/\s*\/\*\*/) { |
| 134 | + $comment = ""; |
| 135 | + while(!eof $header) { |
| 136 | + $line = readline $header; |
| 137 | + $line =~ m/\s*\*?(.*)/; |
| 138 | + $comment .= "$1\n"; |
| 139 | + if ( $line =~ m/\*\/$/ ) { |
| 140 | + last; |
56 | 141 | }
|
57 |
| - $line .= "\n{\n%TypeHeaderCode\n#include \"" . basename($headerfile) . "\"\n%End"; |
58 |
| - $line .= "\n%Docstring\n$comment\n%End\n"; |
| 142 | + } |
| 143 | + next; |
| 144 | + } |
59 | 145 |
|
60 |
| - my $skip; |
61 |
| - # Skip opening curly bracket, we already added that above |
62 |
| - $skip = readline $header; |
63 |
| - $skip =~ m/^\s*{\s$/ || die "Unexpected content on line $line"; |
| 146 | + # Private members (exclude SIP_RUN) |
| 147 | + if ( $line =~ m/^\s*private( slots)?:.*$/ ) { |
| 148 | + $PRIVATE_SECTION = 1; |
| 149 | + $private_section_line = $line; |
| 150 | + next; |
| 151 | + } |
| 152 | + if ( $PRIVATE_SECTION == 1 ) { |
| 153 | + if ( $SIP_RUN == 0) { |
| 154 | + if ( $line =~ m/^\s*(public|protected)( slots)?:.*$/ || $line =~ m/^\s*\};.*$/) { |
| 155 | + $PRIVATE_SECTION = 0; |
| 156 | + } |
| 157 | + else { |
| 158 | + next; |
| 159 | + } |
64 | 160 | }
|
| 161 | + } |
65 | 162 |
|
66 |
| - $line =~ s/SIP_FACTORY/\/Factory\//; |
67 |
| - $line =~ s/SIP_SKIP/\/\//; |
68 |
| - $line =~ s/SIP_OUT/\/Out\//g; |
69 |
| - $line =~ s/SIP_INOUT/\/In,Out\//g; |
70 |
| - $line =~ s/SIP_TRANSFER/\/Transfer\//g; |
71 |
| - $line =~ s/SIP_PYNAME\((\w+)\)/\/PyName=$1\//; |
72 |
| - $line =~ s/SIP_KEEPREFERENCE\((\w+)\)/\/KeepReference\//; |
73 |
| - $line =~ s/SIP_TRANSFERTHIS\((\w+)\)/\/TransferThis\//; |
74 |
| - $line =~ s/SIP_TRANSFERBACK\((\w+)\)/\/TransferBack\//; |
75 |
| - |
76 |
| - $line =~ s/override;/;/g; |
| 163 | + # save comments and do not print them, except in SIP_RUN |
| 164 | + if ( $SIP_RUN == 0 ) { |
| 165 | + if ( $line =~ m/^\s*\/\// ) { |
| 166 | + $line =~ s/^\s*\/\/\!*\s*(.*)$/$1/; |
| 167 | + $comment = $line; |
| 168 | + next; |
| 169 | + } |
77 | 170 | }
|
78 | 171 |
|
79 |
| - # In block comment |
80 |
| - if ($DOXYGEN_BLOCK == $context) { |
81 |
| - if ($line =~ m/\*\//) { |
82 |
| - $context = $GLOBAL; |
| 172 | + # class declaration started |
| 173 | + if ( $line =~ m/^(\s*class)\s*([A-Z]+_EXPORT)(\s+\w+)(\s*\:.*)?$/ ) { |
| 174 | + $line = "$1$3"; |
| 175 | + # Inheritance |
| 176 | + if ($4) { |
| 177 | + my $m; |
| 178 | + $m = $4; |
| 179 | + $m =~ s/public //g; |
| 180 | + $m =~ s/\s*private \w+,?//; |
| 181 | + $line .= $m; |
83 | 182 | }
|
84 |
| - $line =~ m/\s*\*?(.*)/; |
85 |
| - $comment .= "$1\n"; |
| 183 | + |
| 184 | + $line .= "\n{\n%Docstring\n$comment\n%End\n"; |
| 185 | + $line .= "\n%TypeHeaderCode\n#include \"" . basename($headerfile) . "\"\n"; |
| 186 | + |
| 187 | + print $line; |
| 188 | + |
| 189 | + my $skip; |
| 190 | + # Skip opening curly bracket, we already added that above |
| 191 | + $skip = readline $header; |
| 192 | + $skip =~ m/^\s*{\s$/ || die "Unexpected content on line $line"; |
| 193 | + |
| 194 | + $HEADER_CODE = 1; |
86 | 195 | next;
|
87 | 196 | }
|
88 | 197 |
|
| 198 | + # Enum declaration |
| 199 | + if ( $line =~ m/^\s*enum\s+\w+.*?$/ ) { |
| 200 | + print $line; |
| 201 | + $line = readline $header; |
| 202 | + $line =~ m/^\s*\{\s*$/ || die 'Unexpected content: enum should be followed by {'; |
| 203 | + print $line; |
| 204 | + while(!eof $header) { |
| 205 | + $line = readline $header; |
| 206 | + if ($line =~ m/\}/) { |
| 207 | + last; |
| 208 | + } |
| 209 | + $line =~ s/(\s*\w+)(\s*=\s*\w+.*?)?(,?).*$/$1$3/; |
| 210 | + print $line; |
| 211 | + } |
| 212 | + } |
| 213 | + |
| 214 | + # remove keywords |
| 215 | + do {no warnings 'uninitialized'; |
| 216 | + $line =~ s/\s*override( SIP_FACTORY)?;/$1;/; |
| 217 | + $line =~ s/^(\s*)?(const )?(virtual |static )?inline /$1$2$3/; |
| 218 | + $line =~ s/\bnullptr\b/0/g; |
| 219 | + |
| 220 | + # remove function bodies |
| 221 | + if ( $line =~ m/^(\s*)?(const )?(virtual |static )?((\w+(<.*?>)?\s+(\*|&)?)?(\w+|operator.)\(.*?(\(.*\))*.*\)( const)?)\s*(\{.*\})?(?!;)$/ ) { |
| 222 | + my $newline = "$1$2$3$4;\n"; |
| 223 | + if ($line !~ m/\{.*?\}$/) { |
| 224 | + $line = readline $header; |
| 225 | + if ( $line =~ m/^\s*\{\s*$/ ) { |
| 226 | + while(!eof $header) { |
| 227 | + $line = readline $header; |
| 228 | + if ( $line =~ m/\}\s*$/ ) { |
| 229 | + last; |
| 230 | + } |
| 231 | + } |
| 232 | + } |
| 233 | + } |
| 234 | + $line = $newline; |
| 235 | + } |
| 236 | + }; |
| 237 | + |
| 238 | + # deleted functions |
| 239 | + if ( $line =~ m/^(\s*)?(const )?(virtual |static )?((\w+(<.*?>)?\s+(\*|&)?)?(\w+|operator.)\(.*?(\(.*\))*.*\)( const)?)\s*= delete;$/ ) { |
| 240 | + $line = readline $header; |
| 241 | + } |
| 242 | + |
| 243 | + $line =~ s/SIP_FACTORY/\/Factory\//; |
| 244 | + $line =~ s/SIP_OUT/\/Out\//g; |
| 245 | + $line =~ s/SIP_INOUT/\/In,Out\//g; |
| 246 | + $line =~ s/SIP_TRANSFER/\/Transfer\//g; |
| 247 | + $line =~ s/SIP_PYNAME\(\s*(\w+)\s*\)/\/PyName=$1\//; |
| 248 | + $line =~ s/SIP_KEEPREFERENCE\((\w+)\)/\/KeepReference\//; |
| 249 | + $line =~ s/SIP_TRANSFERTHIS\((\w+)\)/\/TransferThis\//; |
| 250 | + $line =~ s/SIP_TRANSFERBACK\((\w+)\)/\/TransferBack\//; |
| 251 | + |
| 252 | + # fix astyle placing space after % character |
| 253 | + $line =~ s/\s*% (MappedType|TypeHeaderCode|ConvertFromTypeCode|ConvertToTypeCode|MethodCode|End)/%$1/; |
| 254 | + $line =~ s/\/\s+GetWrapper\s+\//\/GetWrapper\//; |
| 255 | + |
89 | 256 | print $line;
|
90 | 257 | }
|
0 commit comments