Skip to content

Commit 77d7236

Browse files
committedMar 30, 2017
sipify improvements
* remove enum value assignments * remove deleted functions * remove private members * remove function bodies * remove keywords (override, inline) * comment out but print SIP_SKIP * allow use of #if(n)def SIP_RUN and remove code in #else statements * fix PyName * fix SIP_SKIP * add a list of auto-generated sip files and a script to build them at once
1 parent ba6f736 commit 77d7236

File tree

3 files changed

+232
-51
lines changed

3 files changed

+232
-51
lines changed
 

‎python/auto_sipfiles.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
core/qgsfeature.h
2+
core/qgsvectorlayer.h

‎scripts/sipify.pl

Lines changed: 218 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,88 +3,255 @@
33
use warnings;
44
use File::Basename;
55

6+
# TODO add contexts for
7+
# "multiline function signatures"
8+
# docustrings for QgsFeature::QgsAttributes
9+
610
my $headerfile = $ARGV[0];
711

812
open(my $header, "<", $headerfile) || die "Couldn't open '".$headerfile."' for reading because: ".$!;
913

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;
1218

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;
2019
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+
2129

2230
while(!eof $header) {
2331
my $line = readline $header;
32+
#print $line;
2433

2534
# 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 {
28106
next;
29107
}
30108
}
109+
110+
# TYPE HEADER CODE
111+
if ( $HEADER_CODE && $SIP_RUN == 0 ) {
112+
$HEADER_CODE = 0;
113+
print "%End\n";
114+
}
115+
31116
# Skip forward declarations
32117
if ($line =~ m/^\s*class \w+;$/) {
33118
next;
34119
}
35120
# 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).*?$/) {
37122
next;
38123
}
39124

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;
56141
}
57-
$line .= "\n{\n%TypeHeaderCode\n#include \"" . basename($headerfile) . "\"\n%End";
58-
$line .= "\n%Docstring\n$comment\n%End\n";
142+
}
143+
next;
144+
}
59145

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+
}
64160
}
161+
}
65162

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+
}
77170
}
78171

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;
83182
}
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;
86195
next;
87196
}
88197

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+
89256
print $line;
90257
}

‎scripts/sipify_all.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
3+
DIR=$(git rev-parse --show-toplevel)
4+
5+
set -e
6+
7+
while read -r line; do
8+
header="src/$line"
9+
sipfile=$(sed -E 's/(.*)\.h/python\/\1.sip/' <<< $line)
10+
echo "$header"
11+
${DIR}/scripts/sipify.pl ${DIR}/$header > ${DIR}/$sipfile
12+
done < ${DIR}/python/auto_sipfiles.txt

0 commit comments

Comments
 (0)
Please sign in to comment.