22use strict;
33use warnings;
44use File::Basename;
5+ use Getopt::Long;
56
67use constant PRIVATE => 0;
78use constant PROTECTED => 1;
89use constant PUBLIC => 2;
910
10- # TODO add contexts for
11- # "multiline function signatures"
12- # docustrings for QgsFeature::QgsAttributes
11+ # read arguments
12+ my $debug = 0;
13+ GetOptions (" debug" => \$debug ) or die (" Error in command line arguments\n " );
14+ my $headerfile = $ARGV [0];
1315
1416sub processDoxygenLine
1517{
@@ -38,8 +40,7 @@ sub processDoxygenLine
3840 return " $line \n " ;
3941}
4042
41- my $headerfile = $ARGV [0];
42-
43+ # read file
4344open (my $handle , " <" , $headerfile ) || die " Couldn't open '" .$headerfile ." ' for reading because: " .$! ;
4445chomp (my @lines = <$handle >);
4546close $handle ;
@@ -71,26 +72,40 @@ sub processDoxygenLine
7172push @output , " * Do not edit manually ! Edit header and run scripts/sipify.pl again *\n " ;
7273push @output , " ************************************************************************/\n " ;
7374
75+ # write some code in front of line to know where the output comes from
76+ $debug == 0 or push @output , " CODE SIP_RUN MultiLine\n " ;
77+ sub dbg
78+ {
79+ my $msg = ' ' ;
80+ $debug == 0 or $msg = sprintf (" %-4s %-1d %-1d " , $_ [0], $SIP_RUN , $MULTILINE_DEFINITION );
81+ return $msg ;
82+ }
83+ sub dbg_info
84+ {
85+ $debug == 0 or push @output , $_ [0]." \n " ;
86+ }
87+
88+ # main loop
7489while ($line_idx < $line_count ){
7590 $line = $lines [$line_idx ];
7691 $line_idx ++;
7792 # print "$line\n";
7893
7994 if ($line =~ m / ^\s *SIP_FEATURE\( (\w +) \) (.*)$ / ){
80- push @output , " %Feature $1$2 \n " ;
95+ push @output , dbg( " SF1 " ). " %Feature $1$2 \n " ;
8196 next ;
8297 }
8398 if ($line =~ m / ^\s *SIP_IF_FEATURE\( (\! ?\w +) \) (.*)$ / ){
84- push @output , " %If ($1 )$2 \n " ;
99+ push @output , dbg( " SF2 " ). " %If ($1 )$2 \n " ;
85100 next ;
86101 }
87102 if ($line =~ m / ^\s *SIP_CONVERT_TO_SUBCLASS_CODE(.*)$ / ){
88- push @output , " %ConvertToSubClassCode$1 \n " ;
103+ push @output , dbg( " SCS " ). " %ConvertToSubClassCode$1 \n " ;
89104 next ;
90105 }
91106
92107 if ($line =~ m / ^\s *SIP_END(.*)$ / ){
93- push @output , " %End$1 \n " ;
108+ push @output , dbg( " SEN " ). " %End$1 \n " ;
94109 next ;
95110 }
96111
@@ -99,6 +114,7 @@ sub processDoxygenLine
99114
100115 # skip #if 0 blocks
101116 if ( $line =~ m / ^\s *#if 0/ ){
117+ dbg_info(" skipping #if 0 block" );
102118 my $nesting_index = 0;
103119 while ($line_idx < $line_count ){
104120 $line = $lines [$line_idx ];
@@ -120,7 +136,7 @@ sub processDoxygenLine
120136 if ( $line =~ m / ^\s *#ifdef SIP_RUN/ ){
121137 $SIP_RUN = 1;
122138 if ($ACCESS == PRIVATE){
123- push @output , $private_section_line ." \n " ;
139+ push @output , dbg( " PRV1 " ). $private_section_line ." \n " ;
124140 }
125141 next ;
126142 }
@@ -171,7 +187,7 @@ sub processDoxygenLine
171187 elsif ( $line =~ m / ^\s *#else/ && $global_nesting_index == 0 ){
172188 # code here will be printed out
173189 if ($ACCESS == PRIVATE){
174- push @output , $private_section_line ." \n " ;
190+ push @output , dbg( " PRV2 " ). $private_section_line ." \n " ;
175191 }
176192 $SIP_RUN = 1;
177193 last ;
@@ -197,7 +213,7 @@ sub processDoxygenLine
197213 # TYPE HEADER CODE
198214 if ( $HEADER_CODE && $SIP_RUN == 0 ){
199215 $HEADER_CODE = 0;
200- push @output , " %End \n " ;
216+ push @output , dbg( " HCE " ). " %End \n " ;
201217 }
202218
203219 # Skip forward declarations
@@ -219,11 +235,13 @@ sub processDoxygenLine
219235 $opening_line = pop (@output );
220236 $#output >= 0 or die ' could not reach opening definition' ;
221237 }
238+ dbg_info(" removed multiline definition of SIP_SKIP method" );
222239 $MULTILINE_DEFINITION = 0;
223240 }
224241 # also skip method body if there is one
225242 if ($lines [$line_idx ] =~ m / ^\s *\{ / ){
226243 my $nesting_index = 0;
244+ dbg_info(" skipping method body of SIP_SKIP method" );
227245 while ($line_idx < $line_count ){
228246 $line = $lines [$line_idx ];
229247 $line_idx ++;
@@ -271,7 +289,7 @@ sub processDoxygenLine
271289 $comment = ' ' ;
272290 }
273291 elsif ( $ACCESS == PRIVATE && $line =~ m / SIP_FORCE/ ){
274- push @output , $private_section_line ." \n " ;
292+ push @output , dbg( " PRV3 " ). $private_section_line ." \n " ;
275293 }
276294 elsif ( $ACCESS == PRIVATE && $SIP_RUN == 0 ) {
277295 $comment = ' ' ;
@@ -298,7 +316,7 @@ sub processDoxygenLine
298316 }
299317 }
300318 $comment =~ s /\n +$// ;
301- # push @output, $comment;
319+ # push @output, dbg("XXX"). $comment;
302320 next ;
303321 }
304322
@@ -341,7 +359,7 @@ sub processDoxygenLine
341359 }
342360 $line .= " \n %TypeHeaderCode \n #include \" " . basename($headerfile ) . " \" " ;
343361
344- push @output , " $line \n " ;
362+ push @output , dbg( " CLS " ). " $line \n " ;
345363
346364 # Skip opening curly bracket, we already added that above
347365 my $skip = $lines [$line_idx ];
@@ -356,7 +374,7 @@ sub processDoxygenLine
356374
357375 # Enum declaration
358376 if ( $line =~ m / ^\s *enum\s +\w +.*?$ / ){
359- push @output , " $line \n " ;
377+ push @output , dbg( " ENU1 " ). " $line \n " ;
360378 if ($line =~ m /\{ ((\s *\w +)(\s *=\s *[\w\s\d <|]+.*?)?(,?))+\s *\} / ){
361379 # one line declaration
362380 $line !~ m / =/ or die ' spify.pl does not handle enum one liners with value assignment. Use multiple lines instead.' ;
@@ -367,17 +385,17 @@ sub processDoxygenLine
367385 $line = $lines [$line_idx ];
368386 $line_idx ++;
369387 $line =~ m / ^\s *\{\s *$ / || die " Unexpected content: enum should be followed by {\n line: $line " ;
370- push @output , " $line \n " ;
388+ push @output , dbg( " ENU2 " ). " $line \n " ;
371389 while ($line_idx < $line_count ){
372390 $line = $lines [$line_idx ];
373391 $line_idx ++;
374392 if ($line =~ m /\} ;/ ){
375393 last ;
376394 }
377395 $line =~ s / (\s *\w +)(\s *=\s *[\w\s\d <|]+.*?)?(,?).*$/ $1$3 / ;
378- push @output , " $line \n " ;
396+ push @output , dbg( " ENU3 " ). " $line \n " ;
379397 }
380- push @output , " $line \n " ;
398+ push @output , dbg( " ENU4 " ). " $line \n " ;
381399 # enums don't have Docstring apparently
382400 $comment = ' ' ;
383401 next ;
@@ -386,11 +404,13 @@ sub processDoxygenLine
386404
387405 # skip non-method member declaration in non-public sections
388406 if ( $SIP_RUN != 1 && $ACCESS != PUBLIC && $line =~ m / ^\s *(?:mutable\s )?\w +[\w <> *&:,] * \* ?\w +( = \w +(\( [^()]+\) )?)?;/ ){
407+ dbg_info(" skip non-method member declaration in non-public sections" );
389408 next ;
390409 }
391410
392411 # remove struct member assignment
393412 if ( $SIP_RUN != 1 && $ACCESS == PUBLIC && $line =~ m / ^(\s *\w +[\w <> *&:,]* \* ?\w +) = \w +(\( [^()]+\) )?;/ ){
413+ dbg_info(" remove struct member assignment" );
394414 $line = " $1 ;" ;
395415 }
396416
@@ -417,6 +437,7 @@ sub processDoxygenLine
417437 if ( $MULTILINE_DEFINITION == 1 ){
418438 my $virtual_line = $line ;
419439 my $virtual_line_idx = $line_idx ;
440+ dbg_info(" handle multiline definition to add virtual keyword on opening line" );
420441 while ( $virtual_line !~ m / ^[^()] *\( ([^()]*\( [^()]*\) [^()]*)*[^()] *$ / ){
421442 $virtual_line_idx --;
422443 $virtual_line = $lines [$virtual_line_idx ];
@@ -441,11 +462,14 @@ sub processDoxygenLine
441462
442463 # remove constructor definition, function bodies, member initializing list
443464 if ( $SIP_RUN != 1 && $line =~ m / ^(\s *)?(explicit )?(virtual )?(static |const )*(([\w :]+(<.*?>)?\s +(\* |&)?)?(\w +|operator.{1,2})\( [\w =()\/ ,&*<>:-]*\) ( (?:const|SIP_[A-Z_]*?))*)\s *(\{ .*\} )?(?!;)(\s *\/\/ .*)?$ / ){
465+ dbg_info(" remove constructor definition, function bodies, member initializing list" );
444466 my $newline = " $1$2$3$4$5 ;" ;
445- if ($line !~ m /\{ .*?\} $ / ){
467+ if ($line !~ m /\{ .*?\}\s *(\/\/ .*)?$ / ){
468+ dbg_info(" go for multiline" );
446469 $line = $lines [$line_idx ];
447470 $line_idx ++;
448471 while ( $line =~ m / ^\s *[:,] [\w <>] +\( .*?\) / ){
472+ dbg_info(" member initializing list" );
449473 $line = $lines [$line_idx ];
450474 $line_idx ++;
451475 }
@@ -454,7 +478,6 @@ sub processDoxygenLine
454478 while ($line_idx < $line_count ){
455479 $line = $lines [$line_idx ];
456480 $line_idx ++;
457-
458481 $nesting_index += $line =~ tr / \{// ;
459482 $nesting_index -= $line =~ tr / \}// ;
460483 if ($nesting_index == 0){
@@ -542,14 +565,16 @@ sub processDoxygenLine
542565 $line =~ s /\s *% (MappedType|TypeCode|TypeHeaderCode|ConvertFromTypeCode|ConvertToTypeCode|MethodCode|End)/ %$1 / ;
543566 $line =~ s /\/\s +GetWrapper\s +\/ / \/ GetWrapper\/ / ;
544567
545- push @output , " $line \n " ;
568+ push @output , dbg( " NOR " ). " $line \n " ;
546569
547570 # multiline definition (parenthesis left open)
548571 if ( $MULTILINE_DEFINITION == 1 ){
549- if ( $line =~ m / ^[^()] *([^()]*\( [^()]*\) [^()]*)*\) [^()] *$ / ){
572+ # see https://regex101.com/r/DN01iM/2
573+ if ( $line =~ m / ^([^()]+(\( (?:[^()]++|(?1))*\) ))*[^()] *\) [^()] *$ / ){
550574 $MULTILINE_DEFINITION = 0;
551575 # remove potential following body
552- if ( $lines [$line_idx ] =~ m / ^\s *\{ $ / ){
576+ if ( $SIP_RUN == 0 && $lines [$line_idx ] =~ m / ^\s *\{ $ / ){
577+ dbg_info(" remove following body of multiline def" );
553578 my $last_line = $line ;
554579 my $nesting_index = 0;
555580 while ($line_idx < $line_count ){
@@ -563,8 +588,8 @@ sub processDoxygenLine
563588 }
564589 }
565590 # add missing semi column
566- pop (@output );
567- push @output , " $last_line ;\n " ;
591+ my $dummy = pop (@output );
592+ push @output , dbg( " MLT " ). " $last_line ;\n " ;
568593 }
569594 }
570595 else
@@ -573,6 +598,7 @@ sub processDoxygenLine
573598 }
574599 }
575600 elsif ( $line =~ m / ^[^()] +\( [^()] *([^()]*\( [^()]*\) [^()]*)*[^)] *$ / ){
601+ dbg_info(" Mulitline detected" );
576602 $MULTILINE_DEFINITION = 1;
577603 next ;
578604 }
@@ -592,14 +618,14 @@ sub processDoxygenLine
592618 # parent class Docstring
593619 }
594620 else {
595- push @output , " %Docstring \n " ;
621+ push @output , dbg( " CM1 " ). " %Docstring \n " ;
596622 if ( $comment !~ m / ^\s *$ / ){
597- push @output , " $comment \n " ;
623+ push @output , dbg( " CM2 " ). " $comment \n " ;
598624 }
599625 if ($return_type ne ' ' ){
600- push @output , " :rtype: $return_type \n " ;
626+ push @output , dbg( " CM3 " ). " :rtype: $return_type \n " ;
601627 }
602- push @output , " %End \n " ;
628+ push @output , dbg( " CM4 " ). " %End \n " ;
603629 }
604630 $comment = ' ' ;
605631 $return_type = ' ' ;
0 commit comments