2017-03-17 10:47:01 +01:00
#!/usr/bin/perl
use strict ;
use warnings ;
use File::Basename ;
2017-04-07 08:50:57 +02:00
use constant PRIVATE = > 0 ;
use constant PROTECTED = > 1 ;
use constant PUBLIC = > 2 ;
2017-03-27 09:27:12 +02:00
# TODO add contexts for
# "multiline function signatures"
# docustrings for QgsFeature::QgsAttributes
2017-04-02 20:52:50 +10:00
sub processDoxygenLine
{
2017-04-03 13:14:52 +10:00
my $ line = $ _ [ 0 ] ;
# remove \a formatting
2017-04-17 13:49:59 +10:00
$ line =~ s/\\a (.+?)\b/``$1``/g ;
2017-04-05 10:32:27 +10:00
# replace :: with . (changes c++ style namespace/class directives to Python style)
$ line =~ s/::/./g ;
2017-04-07 09:23:24 +10:00
# replace nullptr with None (nullptr means nothing to Python devs)
$ line =~ s/\bnullptr\b/None/g ;
2017-04-07 11:23:53 +10:00
# replace \returns with :return:
$ line =~ s/\\return(s)?/:return:/g ;
2017-04-07 09:19:34 +10:00
2017-04-03 13:14:52 +10:00
if ( $ line =~ m/[\\@](ingroup|class)/ ) {
2017-04-02 21:28:20 +10:00
return ""
}
2017-04-03 13:14:52 +10:00
if ( $ line =~ m/\\since .*?([\d\.]+)/i ) {
2017-04-02 20:52:50 +10:00
return ".. versionadded:: $1\n" ;
}
2017-04-03 13:14:52 +10:00
if ( $ line =~ m/[\\@]note (.*)/ ) {
2017-04-02 20:52:50 +10:00
return ".. note::\n\n $1\n" ;
}
2017-04-03 13:14:52 +10:00
if ( $ line =~ m/[\\@]brief (.*)/ ) {
2017-04-02 21:28:20 +10:00
return " $1\n" ;
}
2017-04-20 11:18:29 +02:00
return "$line\n" ;
2017-04-02 20:52:50 +10:00
}
2017-03-17 10:47:01 +01:00
my $ headerfile = $ ARGV [ 0 ] ;
2017-04-20 11:18:29 +02:00
open ( my $ handle , "<" , $ headerfile ) || die "Couldn't open '" . $ headerfile . "' for reading because: " . $! ;
chomp ( my @ lines = <$handle> ) ;
close $ handle ;
2017-03-17 10:47:01 +01:00
2017-03-27 09:27:12 +02:00
# contexts
my $ SIP_RUN = 0 ;
my $ HEADER_CODE = 0 ;
2017-04-07 08:50:57 +02:00
my $ ACCESS = PUBLIC ;
2017-03-28 09:06:45 +02:00
my $ MULTILINE_DEFINITION = 0 ;
2017-03-17 10:47:01 +01:00
2017-03-27 14:41:33 +02:00
my $ comment = '' ;
2017-03-27 09:27:12 +02:00
my $ nesting_index = 0 ;
my $ private_section_line = '' ;
2017-04-03 13:53:29 +10:00
my $ classname = '' ;
2017-04-07 11:23:53 +10:00
my $ return_type = '' ;
2017-04-17 11:03:02 +10:00
my $ is_override = 0 ;
2017-04-03 13:53:29 +10:00
my % qflag_hash ;
2017-03-27 09:27:12 +02:00
2017-04-20 11:18:29 +02:00
my $ line_count = @ lines ;
my $ line_idx = - 1 ;
my $ line ;
my @ output = ( ) ;
2017-03-27 09:27:12 +02:00
2017-04-20 11:18:29 +02:00
push @ output , "/************************************************************************\n" ;
push @ output , " * This file has been generated automatically from *\n" ;
push @ output , " * *\n" ;
push @ output , sprintf " * %-*s *\n" , 68 , $ headerfile ;
push @ output , " * *\n" ;
push @ output , " * Do not edit manually ! Edit header and run scripts/sipify.pl again *\n" ;
push @ output , " ************************************************************************/\n" ;
2017-03-17 10:47:01 +01:00
2017-04-20 11:18:29 +02:00
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
#push @output, "$line\n";
2017-03-17 10:47:01 +01:00
2017-04-02 12:53:31 +02:00
if ( $ line =~ m/^\s*SIP_FEATURE\( (\w+) \)(.*)$/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "%Feature $1$2\n" ;
2017-04-02 12:53:31 +02:00
next ;
}
if ( $ line =~ m/^\s*SIP_IF_FEATURE\( (\!?\w+) \)(.*)$/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "%If ($1)$2\n" ;
2017-04-02 12:53:31 +02:00
next ;
}
if ( $ line =~ m/^\s*SIP_CONVERT_TO_SUBCLASS_CODE(.*)$/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "%ConvertToSubClassCode$1\n" ;
2017-04-02 12:53:31 +02:00
next ;
}
if ( $ line =~ m/^\s*SIP_END(.*)$/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "%End$1\n" ;
2017-04-02 12:53:31 +02:00
next ;
}
2017-03-17 10:47:01 +01:00
# Skip preprocessor stuff
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*#/ ) {
if ( $ line =~ m/^\s*#ifdef SIP_RUN/ ) {
2017-03-27 09:27:12 +02:00
$ SIP_RUN = 1 ;
2017-04-07 08:50:57 +02:00
if ( $ ACCESS == PRIVATE ) {
2017-04-20 11:18:29 +02:00
push @ output , $ private_section_line . "\n" ;
2017-03-27 09:27:12 +02:00
}
next ;
}
2017-03-28 09:06:45 +02:00
if ( $ SIP_RUN == 1 ) {
if ( $ line =~ m/^\s*#endif/ ) {
2017-03-27 09:27:12 +02:00
if ( $ nesting_index == 0 ) {
$ SIP_RUN = 0 ;
next ;
}
else {
$ nesting_index - - ;
}
}
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*#if(def)?\s+/ ) {
2017-03-27 09:27:12 +02:00
$ nesting_index + + ;
}
# if there is an else at this level, code will be ignored i.e. not SIP_RUN
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*#else/ && $ nesting_index == 0 ) {
2017-04-20 11:18:29 +02:00
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*#if(def)?\s+/ ) {
2017-03-27 09:27:12 +02:00
$ nesting_index + + ;
}
2017-03-28 09:06:45 +02:00
elsif ( $ line =~ m/^\s*#endif/ ) {
if ( $ nesting_index == 0 ) {
2017-04-24 08:48:12 +02:00
$ comment = '' ;
2017-03-27 09:27:12 +02:00
$ SIP_RUN = 0 ;
last ;
}
else {
$ nesting_index - - ;
}
}
}
next ;
}
}
2017-03-28 09:06:45 +02:00
elsif ( $ line =~ m/^\s*#ifndef SIP_RUN/ ) {
2017-03-27 09:27:12 +02:00
# code is ignored here
2017-04-20 11:18:29 +02:00
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*#if(def)?\s+/ ) {
2017-03-27 09:27:12 +02:00
$ nesting_index + + ;
}
2017-03-28 09:06:45 +02:00
elsif ( $ line =~ m/^\s*#else/ && $ nesting_index == 0 ) {
2017-03-27 09:27:12 +02:00
# code here will be printed out
2017-04-07 08:50:57 +02:00
if ( $ ACCESS == PRIVATE ) {
2017-04-20 11:18:29 +02:00
push @ output , $ private_section_line . "\n" ;
2017-03-27 09:27:12 +02:00
}
$ SIP_RUN = 1 ;
last ;
}
2017-03-28 09:06:45 +02:00
elsif ( $ line =~ m/^\s*#endif/ ) {
if ( $ nesting_index == 0 ) {
2017-04-24 08:48:12 +02:00
$ comment = '' ;
2017-03-27 09:27:12 +02:00
$ SIP_RUN = 0 ;
last ;
}
else {
$ nesting_index - - ;
}
}
}
next ;
}
else {
2017-03-17 10:47:01 +01:00
next ;
}
}
2017-03-27 09:27:12 +02:00
# TYPE HEADER CODE
2017-03-28 09:06:45 +02:00
if ( $ HEADER_CODE && $ SIP_RUN == 0 ) {
2017-03-27 09:27:12 +02:00
$ HEADER_CODE = 0 ;
2017-04-20 11:18:29 +02:00
push @ output , "%End\n" ;
2017-03-27 09:27:12 +02:00
}
2017-03-17 10:47:01 +01:00
# Skip forward declarations
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*class \w+;$/ ) {
2017-03-17 10:47:01 +01:00
next ;
}
# Skip Q_OBJECT, Q_PROPERTY, Q_ENUM, Q_GADGET
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*Q_(OBJECT|ENUMS|PROPERTY|GADGET|DECLARE_METATYPE).*?$/ ) {
2017-03-17 10:47:01 +01:00
next ;
}
2017-03-27 09:27:12 +02:00
# SIP_SKIP
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/SIP_SKIP/ ) {
2017-04-17 10:49:29 +10:00
$ comment = '' ;
2017-04-20 14:37:22 +02:00
# if multiline definition, remove previous lines
if ( $ MULTILINE_DEFINITION == 1 ) {
my $ opening_line = '' ;
while ( $ opening_line !~ m/^[^()]*\(([^()]*\([^()]*\)[^()]*)*[^()]*$/ ) {
$ opening_line = pop ( @ output ) ;
$# output >= 0 or die 'could not reach opening definition' ;
}
$ MULTILINE_DEFINITION = 0 ;
}
2017-03-27 09:27:12 +02:00
next ;
}
# Private members (exclude SIP_RUN)
2017-03-29 16:15:07 +02:00
if ( $ line =~ m/^\s*private( slots)?:/ ) {
2017-04-07 08:50:57 +02:00
$ ACCESS = PRIVATE ;
2017-03-27 09:27:12 +02:00
$ private_section_line = $ line ;
2017-04-24 08:48:12 +02:00
$ comment = '' ;
2017-03-27 09:27:12 +02:00
next ;
}
2017-04-07 08:50:57 +02:00
elsif ( $ line =~ m/^\s*(public)( slots)?:.*$/ ) {
$ ACCESS = PUBLIC ;
2017-04-24 08:48:12 +02:00
$ comment = '' ;
2017-04-07 08:50:57 +02:00
}
elsif ( $ line =~ m/^\};.*$/ ) {
$ ACCESS = PUBLIC ;
2017-04-24 08:48:12 +02:00
$ comment = '' ;
2017-04-07 08:50:57 +02:00
}
elsif ( $ line =~ m/^\s*(protected)( slots)?:.*$/ ) {
$ ACCESS = PROTECTED ;
2017-04-24 08:48:12 +02:00
$ comment = '' ;
}
elsif ( $ ACCESS == PRIVATE && $ line =~ m/SIP_FORCE/ ) {
push @ output , $ private_section_line . "\n" ;
2017-04-07 08:50:57 +02:00
}
elsif ( $ ACCESS == PRIVATE && $ SIP_RUN == 0 ) {
2017-04-24 08:48:12 +02:00
$ comment = '' ;
2017-04-07 08:50:57 +02:00
next ;
2017-03-27 09:27:12 +02:00
}
2017-04-02 12:53:31 +02:00
# Skip assignment operator
if ( $ line =~ m/operator=\s*\(/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "// $line" ;
2017-04-02 12:53:31 +02:00
next ;
}
2017-03-28 09:06:45 +02:00
# Detect comment block
2017-03-29 16:15:07 +02:00
if ( $ line =~ m/^\s*\/\*/ ) {
do { no warnings 'uninitialized' ;
2017-04-20 11:18:29 +02:00
$ comment = processDoxygenLine ( $ line =~ s/^\s*\/\*(\*)?(.*?)\n?$/$2/ r ) ;
2017-03-29 16:15:07 +02:00
} ;
2017-03-28 09:06:45 +02:00
$ comment =~ s/^\s*$// ;
2017-04-20 11:18:29 +02:00
#$comment =~ s/^(\s*\n)*(.+)/$2/;
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
$ comment . = processDoxygenLine ( $ line =~ s/\s*\*?(.*?)(\/)?\n?$/$1/ r ) ;
2017-04-24 08:48:12 +02:00
if ( $ line =~ m/\*\/\s*(\/\/.*?)?$/ ) {
2017-03-28 09:06:45 +02:00
last ;
}
}
2017-04-20 11:18:29 +02:00
$ comment =~ s/\n+$// ;
#push @output, $comment;
2017-03-28 09:06:45 +02:00
next ;
}
2017-03-27 09:27:12 +02:00
# save comments and do not print them, except in SIP_RUN
2017-03-28 09:06:45 +02:00
if ( $ SIP_RUN == 0 ) {
2017-04-02 21:28:20 +10:00
if ( $ line =~ m/^\s*\/\// ) {
2017-04-20 11:18:29 +02:00
$ line =~ s/^\s*\/\/\!*\s*(.*?)\n?$/$1/ ;
2017-04-02 20:52:50 +10:00
$ comment = processDoxygenLine ( $ line ) ;
2017-04-20 11:18:29 +02:00
$ comment =~ s/\n+$// ;
2017-03-27 09:27:12 +02:00
next ;
}
2017-03-17 10:47:01 +01:00
}
2017-04-07 08:50:57 +02:00
if ( $ line =~ m/^(\s*struct)\s+(\w+)$/ ) {
$ ACCESS = PUBLIC ;
}
2017-03-27 09:27:12 +02:00
# class declaration started
2017-04-05 14:14:25 +02:00
if ( $ line =~ m/^(\s*class)\s*([A-Z]+_EXPORT)?\s+(\w+)(\s*\:.*)?(\s*SIP_ABSTRACT)?$/ ) {
2017-03-30 16:09:33 +02:00
do { no warnings 'uninitialized' ;
2017-04-03 13:53:29 +10:00
$ classname = $ 3 ;
2017-03-30 16:27:41 +02:00
$ line =~ m/\b[A-Z]+_EXPORT\b/ or die "Class$classname in $headerfile should be exported with appropriate [LIB]_EXPORT macro. If this should not be available in python, wrap it in a `#ifndef SIP_RUN` block." ;
2017-03-30 16:09:33 +02:00
} ;
2017-04-03 13:53:29 +10:00
$ line = "$1 $3" ;
2017-03-27 09:27:12 +02:00
# Inheritance
2017-03-28 09:06:45 +02:00
if ( $ 4 ) {
2017-03-29 16:15:07 +02:00
my $ m = $ 4 ;
2017-03-27 09:27:12 +02:00
$ m =~ s/public //g ;
2017-04-05 09:54:27 +02:00
$ m =~ s/,?\s*private \w+(::\w+)?// ;
2017-03-29 16:15:07 +02:00
$ m =~ s/(\s*:)?\s*$// ;
2017-03-27 09:27:12 +02:00
$ line . = $ m ;
2017-03-17 10:47:01 +01:00
}
2017-04-05 14:14:25 +02:00
if ( $ 5 ) {
$ line . = ' /Abstract/' ;
}
2017-03-27 09:27:12 +02:00
2017-03-29 16:15:07 +02:00
$ line . = "\n{\n" ;
if ( $ comment !~ m/^\s*$/ ) {
$ line . = "%Docstring\n$comment\n%End\n" ;
}
2017-04-20 11:18:29 +02:00
$ line . = "\n%TypeHeaderCode\n#include \"" . basename ( $ headerfile ) . "\"" ;
2017-03-27 09:27:12 +02:00
2017-04-20 11:18:29 +02:00
push @ output , "$line\n" ;
2017-03-27 09:27:12 +02:00
# Skip opening curly bracket, we already added that above
2017-04-20 11:18:29 +02:00
my $ skip = $ lines [ $ line_idx ] ;
$ line_idx + + ;
$ skip =~ m/^\s*{\s*$/ || die "Unexpected content on line $skip" ;
2017-03-27 09:27:12 +02:00
2017-03-28 09:06:45 +02:00
$ comment = '' ;
2017-03-27 09:27:12 +02:00
$ HEADER_CODE = 1 ;
2017-04-07 08:50:57 +02:00
$ ACCESS = PRIVATE ;
2017-03-17 10:47:01 +01:00
next ;
}
2017-03-27 09:27:12 +02:00
# Enum declaration
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*enum\s+\w+.*?$/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "$line\n" ;
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-27 09:27:12 +02:00
$ line =~ m/^\s*\{\s*$/ || die 'Unexpected content: enum should be followed by {' ;
2017-04-20 11:18:29 +02:00
push @ output , "$line\n" ;
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/\};/ ) {
2017-03-27 09:27:12 +02:00
last ;
}
2017-04-19 15:03:31 +02:00
$ line =~ s/(\s*\w+)(\s*=\s*[\w\s\d<|]+.*?)?(,?).*$/$1$3/ ;
2017-04-20 11:18:29 +02:00
push @ output , "$line\n" ;
2017-03-27 09:27:12 +02:00
}
2017-04-20 11:18:29 +02:00
push @ output , "$line\n" ;
2017-03-29 16:15:07 +02:00
# enums don't have Docstring apparently
2017-04-17 10:49:29 +10:00
$ comment = '' ;
2017-03-28 09:06:45 +02:00
next ;
2017-03-27 09:27:12 +02:00
}
2017-04-08 10:06:55 +02:00
# skip non-method member declaration in non-public sections
2017-04-19 15:18:54 +02:00
if ( $ SIP_RUN != 1 && $ ACCESS != PUBLIC && $ line =~ m/^\s*(?:mutable\s)?\w+[\w<> *&:,]* \*?\w+( = \w+(\([^()]+\))?)?;/ ) {
2017-04-05 09:46:14 +02:00
next ;
}
2017-04-19 15:49:22 +02:00
# remove struct member assignment
if ( $ SIP_RUN != 1 && $ ACCESS == PUBLIC && $ line =~ m/^(\s*\w+[\w<> *&:,]* \*?\w+) = \w+(\([^()]+\))?;/ ) {
2017-04-20 11:18:29 +02:00
$ line = "$1;" ;
2017-04-19 15:49:22 +02:00
}
2017-04-03 13:53:29 +10:00
# catch Q_DECLARE_FLAGS
if ( $ line =~ m/^(\s*)Q_DECLARE_FLAGS\(\s*(.*?)\s*,\s*(.*?)\s*\)\s*$/ ) {
$ line = "$1typedef QFlags<$classname::$3> $2;\n" ;
$ qflag_hash { "$classname::$2" } = "$classname::$3" ;
}
# catch Q_DECLARE_OPERATORS_FOR_FLAGS
if ( $ line =~ m/^(\s*)Q_DECLARE_OPERATORS_FOR_FLAGS\(\s*(.*?)\s*\)\s*$/ ) {
my $ flag = $ qflag_hash { $ 2 } ;
$ line = "$1QFlags<$flag> operator|($flag f1, QFlags<$flag> f2);\n" ;
}
2017-04-19 11:16:09 +02:00
# remove Q_INVOKABLE
$ line =~ s/^(\s*)Q_INVOKABLE /$1/ ;
2017-03-27 09:27:12 +02:00
do { no warnings 'uninitialized' ;
2017-03-29 16:15:07 +02:00
# remove keywords
2017-04-17 11:03:02 +10:00
if ( $ line =~ m/\boverride\b/ ) {
$ is_override = 1 ;
2017-04-20 13:58:56 +02:00
# handle multiline definition to add virtual keyword on opening line
if ( $ MULTILINE_DEFINITION == 1 ) {
my $ virtual_line = $ line ;
my $ virtual_line_idx = $ line_idx ;
while ( $ virtual_line !~ m/^[^()]*\(([^()]*\([^()]*\)[^()]*)*[^()]*$/ ) {
$ virtual_line_idx - - ;
$ virtual_line = $ lines [ $ virtual_line_idx ] ;
$ virtual_line_idx >= 0 or die 'could not reach opening definition' ;
}
if ( $ virtual_line !~ m/^(\s*)virtual\b(.*)$/ ) {
my $ idx = $# output - $ line_idx + $ virtual_line_idx + 2 ;
#print "len: $#output line_idx: $line_idx virt: $virtual_line_idx\n"idx: $idx\n$output[$idx]\n";
$ output [ $ idx ] = $ virtual_line =~ s/^(\s*?)\b(.*)$/$1 virtual $2\n/ r ;
}
}
elsif ( $ line !~ m/^(\s*)virtual\b(.*)$/ ) {
2017-04-18 11:00:13 +10:00
#sip often requires the virtual keyword to be present, or it chokes on covariant return types
#in overridden methods
2017-04-20 13:58:56 +02:00
$ line =~ s/^(\s*?)\b(.*)$/$1virtual $2\n/ ;
2017-04-18 11:00:13 +10:00
}
2017-04-17 11:03:02 +10:00
}
2017-04-03 09:38:40 +02:00
$ line =~ s/\s*\boverride\b// ;
2017-03-27 09:27:12 +02:00
$ line =~ s/^(\s*)?(const )?(virtual |static )?inline /$1$2$3/ ;
$ line =~ s/\bnullptr\b/0/g ;
2017-04-02 16:21:23 +10:00
$ line =~ s/\s*=\s*default\b//g ;
2017-03-27 09:27:12 +02:00
2017-03-29 16:15:07 +02:00
# remove constructor definition
2017-04-02 10:54:04 +02:00
if ( $ line =~ m/^(\s*)?(explicit )?(\w+)\([\w\=\(\)\s\,\&\*\<\>]*\)(?!;)$/ ) {
2017-03-29 16:15:07 +02:00
my $ newline = $ line =~ s/\n/;\n/ r ;
my $ nesting_index = 0 ;
2017-04-20 11:18:29 +02:00
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-29 16:15:07 +02:00
if ( $ nesting_index == 0 ) {
if ( $ line =~ m/^\s*(:|,)/ ) {
next ;
}
$ line =~ m/^\s*\{/ or die 'Constructor definition misses {' ;
if ( $ line =~ m/^\s*\{.*?\}/ ) {
last ;
}
$ nesting_index = 1 ;
next ;
}
else {
$ nesting_index += $ line =~ tr /\{/ / ;
$ nesting_index -= $ line =~ tr /\}/ / ;
if ( $ nesting_index eq 0 ) {
last ;
}
}
}
$ line = $ newline ;
}
2017-03-27 09:27:12 +02:00
# remove function bodies
2017-04-11 16:21:38 +10:00
if ( $ line =~ m/^(\s*)?(virtual )?(static |const )*(([\w:]+(<.*?>)?\s+(\*|&)?)?(\w+|operator.{1,2})\(.*?(\(.*\))*.*\)( (?:const|SIP_[A-Z_]*?))*)\s*(\{.*\})?(?!;)(\s*\/\/.*)?$/ ) {
2017-04-20 11:18:29 +02:00
my $ newline = "$1$2$3$4;" ;
2017-03-28 09:06:45 +02:00
if ( $ line !~ m/\{.*?\}$/ ) {
2017-04-20 11:18:29 +02:00
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/^\s*\{\s*$/ ) {
2017-04-20 11:18:29 +02:00
while ( $ line_idx < $ line_count ) {
$ line = $ lines [ $ line_idx ] ;
$ line_idx + + ;
2017-03-28 09:06:45 +02:00
if ( $ line =~ m/\}\s*$/ ) {
2017-03-27 09:27:12 +02:00
last ;
}
}
}
}
$ line = $ newline ;
}
2017-04-07 11:23:53 +10:00
2017-04-18 09:53:00 +10:00
# remove inline declarations
if ( $ line =~ m/^(\s*)?(static |const )*(([\w:]+(<.*?>)?\s+(\*|&)?)?(\w+)( (?:const*?))*)\s*(\{.*\});(\s*\/\/.*)?$/ ) {
2017-04-20 11:18:29 +02:00
my $ newline = "$1$3;" ;
2017-04-18 09:53:00 +10:00
$ line = $ newline ;
}
2017-04-07 11:23:53 +10:00
if ( $ line =~ m/^\s*(?:const |virtual |static |inline )*(?!explicit)([\w:]+(?:<.*?>)?)\s+(?:\*|&)?(?:\w+|operator.{1,2})\(.*$/ ) {
if ( $ 1 !~ m/(void|SIP_PYOBJECT|operator|return|QFlag)/ ) {
$ return_type = $ 1 ;
# replace :: with . (changes c++ style namespace/class directives to Python style)
$ return_type =~ s/::/./g ;
# replace with builtin Python types
$ return_type =~ s/\bdouble\b/float/ ;
$ return_type =~ s/\bQString\b/str/ ;
$ return_type =~ s/\bQStringList\b/list of str/ ;
if ( $ return_type =~ m/^(?:QList|QVector)<\s*(.*?)[\s*\*]*>$/ ) {
$ return_type = "list of $1" ;
}
if ( $ return_type =~ m/^QSet<\s*(.*?)[\s*\*]*>$/ ) {
$ return_type = "set of $1" ;
}
}
}
2017-03-27 09:27:12 +02:00
} ;
# deleted functions
2017-04-07 11:23:53 +10:00
if ( $ line =~ m/^(\s*)?(const )?(virtual |static )?((\w+(<.*?>)?\s+(\*|&)?)?(\w+|operator.{1,2})\(.*?(\(.*\))*.*\)( const)?)\s*= delete;(\s*\/\/.*)?$/ ) {
2017-03-29 16:15:07 +02:00
$ comment = '' ;
next ;
2017-03-27 09:27:12 +02:00
}
2017-03-29 16:15:07 +02:00
$ line =~ s/\bSIP_FACTORY\b/\/Factory\// ;
$ line =~ s/\bSIP_OUT\b/\/Out\//g ;
$ line =~ s/\bSIP_INOUT\b/\/In,Out\//g ;
$ line =~ s/\bSIP_TRANSFER\b/\/Transfer\//g ;
$ line =~ s/\bSIP_KEEPREFERENCE\b/\/KeepReference\// ;
$ line =~ s/\bSIP_TRANSFERTHIS\b/\/TransferThis\// ;
$ line =~ s/\bSIP_TRANSFERBACK\b/\/TransferBack\// ;
2017-03-30 17:54:46 +02:00
$ line =~ s/\bSIP_RELEASEGIL\b/\/ReleaseGIL\// ;
2017-03-29 16:15:07 +02:00
2017-03-27 09:27:12 +02:00
$ line =~ s/SIP_PYNAME\(\s*(\w+)\s*\)/\/PyName=$1\// ;
2017-03-30 09:57:22 +02:00
$ line =~ s/(\w+)(\<(?>[^<>]|(?2))*\>)?\s+SIP_PYTYPE\(\s*\'?([^()']+)(\(\s*(?:[^()]++|(?2))*\s*\))?\'?\s*\)/$3/g ;
$ line =~ s/=\s+[^=]*?\s+SIP_PYDEFAULTVALUE\(\s*\'?([^()']+)(\(\s*(?:[^()]++|(?2))*\s*\))?\'?\s*\)/= $1/g ;
2017-03-27 09:27:12 +02:00
2017-04-24 08:48:12 +02:00
$ line =~ s/SIP_FORCE// ;
2017-03-27 09:27:12 +02:00
# fix astyle placing space after % character
$ line =~ s/\s*% (MappedType|TypeHeaderCode|ConvertFromTypeCode|ConvertToTypeCode|MethodCode|End)/%$1/ ;
$ line =~ s/\/\s+GetWrapper\s+\//\/GetWrapper\// ;
2017-04-20 11:18:29 +02:00
push @ output , "$line\n" ;
2017-03-28 09:06:45 +02:00
# multiline definition (parenthesis left open)
if ( $ MULTILINE_DEFINITION == 1 ) {
if ( $ line =~ m/^[^()]*([^()]*\([^()]*\)[^()]*)*\)[^()]*$/ ) {
$ MULTILINE_DEFINITION = 0 ;
}
else
{
next ;
}
}
elsif ( $ line =~ m/^[^()]+\([^()]*([^()]*\([^()]*\)[^()]*)*[^)]*$/ ) {
$ MULTILINE_DEFINITION = 1 ;
next ;
}
# write comment
2017-04-17 10:49:29 +10:00
if ( $ line =~ m/^\s*$/ )
{
2017-04-20 13:58:56 +02:00
$ is_override = 0 ;
2017-04-17 10:49:29 +10:00
next ;
}
elsif ( $ line =~ m/\/\// || $ line =~ m/\s*typedef / || $ line =~ m/\s*struct / ) {
2017-03-28 09:06:45 +02:00
$ comment = '' ;
}
2017-04-07 11:23:53 +10:00
elsif ( $ comment !~ m/^\s*$/ || $ return_type ne '' ) {
2017-04-17 11:03:02 +10:00
if ( $ is_override == 1 && $ comment =~ m/^\s*$/ ) {
# overridden method with no new docs - so don't create a Docstring and use
# parent class Docstring
2017-04-07 11:23:53 +10:00
}
2017-04-17 11:03:02 +10:00
else {
2017-04-20 11:18:29 +02:00
push @ output , "%Docstring\n" ;
2017-04-17 11:03:02 +10:00
if ( $ comment !~ m/^\s*$/ ) {
2017-04-20 11:18:29 +02:00
push @ output , "$comment\n" ;
2017-04-17 11:03:02 +10:00
}
if ( $ return_type ne '' ) {
2017-04-20 11:18:29 +02:00
push @ output , " :rtype: $return_type\n" ;
2017-04-17 11:03:02 +10:00
}
2017-04-20 11:18:29 +02:00
push @ output , "%End\n" ;
2017-04-07 11:23:53 +10:00
}
2017-03-28 09:06:45 +02:00
$ comment = '' ;
2017-04-07 11:23:53 +10:00
$ return_type = '' ;
2017-04-17 11:03:02 +10:00
$ is_override = 0 ;
2017-03-28 09:06:45 +02:00
}
2017-03-17 10:47:01 +01:00
}
2017-04-20 11:18:29 +02:00
push @ output , "/************************************************************************\n" ;
push @ output , " * This file has been generated automatically from *\n" ;
push @ output , " * *\n" ;
push @ output , sprintf " * %-*s *\n" , 68 , $ headerfile ;
push @ output , " * *\n" ;
push @ output , " * Do not edit manually ! Edit header and run scripts/sipify.pl again *\n" ;
push @ output , " ************************************************************************/\n" ;
2017-04-24 07:39:30 +02:00
print join ( '' , @ output ) ;