1414use constant STRICT => 10;
1515use constant UNSTRICT => 11;
1616
17+ use constant MULTILINE_NO => 20;
18+ use constant MULTILINE_METHOD => 21;
19+ use constant MULTILINE_CONDITIONAL_STATEMENT => 22;
20+
1721# read arguments
1822my $debug = 0;
1923die (" usage: $0 [-debug] headerfile\n " ) unless GetOptions (" debug" => \$debug ) && @ARGV == 1;
3539my @ACCESS = (PUBLIC);
3640my @CLASSNAME = ();
3741my @EXPORTED = (0);
38- my $MULTILINE_DEFINITION = 0 ;
42+ my $MULTILINE_DEFINITION = MULTILINE_NO ;
3943my $ACTUAL_CLASS = ' ' ;
44+ my $PYTHON_SIGNATURE = ' ' ;
4045
4146my $COMMENT = ' ' ;
4247my $GLOB_IFDEF_NESTING_IDX = 0;
@@ -135,39 +140,64 @@ sub processDoxygenLine {
135140
136141sub detect_and_remove_following_body_or_initializerlist {
137142 # https://regex101.com/r/ZaP3tC/8
143+ my $python_signature = ' ' ;
138144 do {no warnings ' uninitialized' ;
139145 if ( $LINE =~ m / ^(\s *)?((?:(?:explicit|static|const|unsigned|virtual)\s +)*)(([\w :]+(<.*?>)?\s +[*&]?)?(~?\w +|(\w +::)?operator.{1,2})\s *\( ([\w =()\/ ,&*<>."-]|::)*\) ( +(?:const|SIP_[\w _]+?))*)\s *((\s *[:,]\s +\w +\( .*\) )*\s *\{ .*\}\s *(?:SIP_[\w _]+)?;?|(?!;))(\s *\/\/ .*)?$ /
140146 || $LINE =~ m / SIP_SKIP\s *(?!;)\s *(\/\/ .*)?$ /
141147 || $LINE =~ m / ^\s *class.*SIP_SKIP/ ){
142148 dbg_info(" remove constructor definition, function bodies, member initializing list" );
143149 my $newline = " $1$2$3 ;" ;
144- remove_following_body_or_initializerlist() unless $LINE =~ m / {.*}(\s *SIP_\w +)*\s *(\/\/ .*)?$ / ;
150+ $python_signature = remove_following_body_or_initializerlist() unless $LINE =~ m / {.*}(\s *SIP_\w +)*\s *(\/\/ .*)?$ / ;
145151 $LINE = $newline ;
146152 }
147153 };
154+ return $python_signature ;
148155}
149156
150157sub remove_following_body_or_initializerlist {
158+ my $python_signature = ' ' ;
151159 do {no warnings ' uninitialized' ;
152160 dbg_info(" remove constructor definition, function bodies, member initializing list" );
153- $LINE = read_line();
154- while ( $LINE =~ m / ^\s *[:,] \s +([\w <>]|::)+\( .*?\) / ){
155- dbg_info(" member initializing list" );
156- $LINE = read_line();
161+ my $line = read_line();
162+ # python signature
163+ if ($line =~ m / ^\s *\[\s *(\w +\s *)?\( / ){
164+ dbg_info(" python signature detected" );
165+ my $nesting_index = 0;
166+ while ($LINE_IDX < $LINE_COUNT ){
167+ $nesting_index += $line =~ tr / \[// ;
168+ $nesting_index -= $line =~ tr / \]// ;
169+ if ($nesting_index == 0){
170+ if ($line =~ m / ^(.*);\s *(\/\/ .*)?$ / ){
171+ $line = $1 ; # remove semicolon (added later)
172+ $python_signature .= " \n $line " ;
173+ return $python_signature ;
174+ }
175+ last ;
176+ }
177+ $python_signature .= " \n $line " ;
178+ $line = read_line();
179+ }
157180 }
158- if ( $LINE =~ m / ^\s *\{ / ){
181+ # member initializing list
182+ while ( $line =~ m / ^\s *[:,] \s +([\w <>]|::)+\( .*?\) / ){
183+ dbg_info(" member initializing list" );
184+ $line = read_line();
185+ }
186+ # body
187+ if ( $line =~ m / ^\s *\{ / ){
159188 my $nesting_index = 0;
160189 while ($LINE_IDX < $LINE_COUNT ){
161190 dbg_info(" remove body" );
162- $nesting_index += $LINE =~ tr / \{// ;
163- $nesting_index -= $LINE =~ tr / \}// ;
191+ $nesting_index += $line =~ tr / \{// ;
192+ $nesting_index -= $line =~ tr / \}// ;
164193 if ($nesting_index == 0){
165194 last ;
166195 }
167- $LINE = read_line();
196+ $line = read_line();
168197 }
169198 }
170199 };
200+ return $python_signature ;
171201}
172202
173203sub fix_annotations {
@@ -206,14 +236,14 @@ sub fix_annotations {
206236 # remove argument
207237 if ($line =~ m / SIP_PYARGREMOVE/ ){
208238 dbg_info(" remove arg" );
209- if ( $MULTILINE_DEFINITION == 1 ){
239+ if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
210240 my $prev_line = pop (@OUTPUT ) =~ s /\n $// r ;
211241 # update multi line status
212242 my $parenthesis_balance = 0;
213243 $parenthesis_balance += $prev_line =~ tr / \(// ;
214244 $parenthesis_balance -= $prev_line =~ tr / \)// ;
215245 if ($parenthesis_balance == 1){
216- $MULTILINE_DEFINITION = 0 ;
246+ $MULTILINE_DEFINITION = MULTILINE_NO ;
217247 }
218248 # concat with above line to bring previous commas
219249 $line =~ s / ^\s +// ;
@@ -257,10 +287,10 @@ sub detect_comment_block{
257287# main loop
258288while ($LINE_IDX < $LINE_COUNT ){
259289
290+ $PYTHON_SIGNATURE = ' ' ;
260291 $ACTUAL_CLASS = $CLASSNAME [$#CLASSNAME ] unless $#CLASSNAME < 0;
261292 $LINE = read_line();
262293
263-
264294 if ($LINE =~ m / ^\s *SIP_FEATURE\( (\w +) \) (.*)$ / ){
265295 write_output(" SF1" , " %Feature $1$2 \n " );
266296 next ;
@@ -270,8 +300,8 @@ sub detect_comment_block{
270300 next ;
271301 }
272302 if ($LINE =~ m / ^\s *SIP_CONVERT_TO_SUBCLASS_CODE(.*)$ / ){
273- write_output( " SCS " , " %ConvertToSubClassCode$1 \n " ) ;
274- next ;
303+ $LINE = " %ConvertToSubClassCode$1 " ;
304+ # do not go next, let run the "do not process SIP code"
275305 }
276306
277307 if ($LINE =~ m / ^\s *SIP_END(.*)$ / ){
@@ -284,9 +314,24 @@ sub detect_comment_block{
284314 $IF_FEATURE_CONDITION = $1 ;
285315 }
286316
317+ # do not process SIP code %XXXCode
318+ if ( $SIP_RUN == 1 && $LINE =~ m / ^ *% *(MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$ / ){
319+ $LINE = " %$1$2 " ;
320+ $COMMENT = ' ' ;
321+ dbg_info(" do not process SIP code" );
322+ while ( $LINE !~ m / ^ *% *End/ ){
323+ write_output(" COD" , $LINE ." \n " );
324+ $LINE = read_line();
325+ $LINE =~ s / ^ *% *(MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/ %$1$2 / ;
326+ $LINE =~ s / ^\s *SIP_END(.*)$/ %End$1 / ;
327+ }
328+ $LINE =~ s / ^\s *% End/ %End / ;
329+ write_output(" COD" , $LINE ." \n " );
330+ next ;
331+ }
332+
287333 # Skip preprocessor stuff
288334 if ($LINE =~ m / ^\s *#/ ){
289-
290335 # skip #if 0 blocks
291336 if ( $LINE =~ m / ^\s *#if (0|defined\( Q_OS_WIN\) )/ ){
292337 dbg_info(" skipping #if $1 block" );
@@ -412,15 +457,15 @@ sub detect_comment_block{
412457 dbg_info(' SIP SKIP!' );
413458 $COMMENT = ' ' ;
414459 # if multiline definition, remove previous lines
415- if ( $MULTILINE_DEFINITION == 1 ){
460+ if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
416461 dbg_info(' SIP_SKIP with MultiLine' );
417462 my $opening_line = ' ' ;
418463 while ( $opening_line !~ m / ^[^()] *\( ([^()]*\( [^()]*\) [^()]*)*[^()] *$ / ){
419464 $opening_line = pop (@OUTPUT );
420465 $#OUTPUT >= 0 or exit_with_error(' could not reach opening definition' );
421466 }
422467 dbg_info(" removed multiline definition of SIP_SKIP method" );
423- $MULTILINE_DEFINITION = 0 ;
468+ $MULTILINE_DEFINITION = MULTILINE_NO ;
424469 }
425470 # also skip method body if there is one
426471 detect_and_remove_following_body_or_initializerlist();
@@ -704,7 +749,7 @@ sub detect_comment_block{
704749 # remove keywords
705750 if ( $IS_OVERRIDE == 1 ){
706751 # handle multiline definition to add virtual keyword on opening line
707- if ( $MULTILINE_DEFINITION == 1 ){
752+ if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
708753 my $virtual_line = $LINE ;
709754 my $virtual_line_idx = $LINE_IDX ;
710755 dbg_info(" handle multiline definition to add virtual keyword on opening line" );
@@ -728,7 +773,7 @@ sub detect_comment_block{
728773 }
729774
730775 # remove constructor definition, function bodies, member initializing list
731- $SIP_RUN == 1 or detect_and_remove_following_body_or_initializerlist();
776+ $PYTHON_SIGNATURE = detect_and_remove_following_body_or_initializerlist();
732777
733778 # remove inline declarations
734779 if ( $LINE =~ m / ^(\s *)?(static |const )*(([\w :]+(<.*?>)?\s +(\* |&)?)?(\w +)( (?:const*?))*)\s *(\{ .*\} );(\s *\/\/ .*)?$ / ){
@@ -768,27 +813,29 @@ sub detect_comment_block{
768813 $LINE = fix_annotations($LINE );
769814
770815 # fix astyle placing space after % character
771- $LINE =~ s /\s *% (MappedType|Type(Header)?Code|Module(Header)?Code|Convert(From|To)TypeCode|MethodCode|End)/ %$1 / ;
772816 $LINE =~ s /\/\s +GetWrapper\s +\/ / \/ GetWrapper\/ / ;
773817
774818 write_output(" NOR" , " $LINE \n " );
819+ if ($PYTHON_SIGNATURE ne ' ' ){
820+ write_output(" PSI" , " $PYTHON_SIGNATURE \n " );
821+ }
775822
776823 # multiline definition (parenthesis left open)
777- if ( $MULTILINE_DEFINITION == 1 ){
824+ if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
778825 dbg_info(" on multiline" );
779826 # https://regex101.com/r/DN01iM/2
780827 if ( $LINE =~ m / ^([^()]+(\( (?:[^()]++|(?1))*\) ))*[^()] *\) [^()] *$ / ){
781- $MULTILINE_DEFINITION = 0;
782828 dbg_info(" ending multiline" );
783829 # remove potential following body
784- if ( $SIP_RUN == 0 && $LINE !~ m / (\{ .*\} |;)\s *(\/\/ .*)?$ / ){
830+ if ( $MULTILINE_DEFINITION != MULTILINE_CONDITIONAL_STATEMENT && $LINE !~ m / (\{ .*\} |;)\s *(\/\/ .*)?$ / ){
785831 dbg_info(" remove following body of multiline def" );
786832 my $last_line = $LINE ;
787- remove_following_body_or_initializerlist();
833+ $last_line .= remove_following_body_or_initializerlist();
788834 # add missing semi column
789835 my $dummy = pop (@OUTPUT );
790836 write_output(" MLT" , " $last_line ;\n " );
791837 }
838+ $MULTILINE_DEFINITION = MULTILINE_NO;
792839 }
793840 else
794841 {
@@ -797,7 +844,12 @@ sub detect_comment_block{
797844 }
798845 elsif ( $LINE =~ m / ^[^()] +\( [^()] *([^()]*\( [^()]*\) [^()]*)*[^)] *$ / ){
799846 dbg_info(" Mulitline detected" );
800- $MULTILINE_DEFINITION = 1;
847+ if ( $LINE =~ m / ^\s *((else )?if|while|for) *\( / ){
848+ $MULTILINE_DEFINITION = MULTILINE_CONDITIONAL_STATEMENT;
849+ }
850+ else {
851+ $MULTILINE_DEFINITION = MULTILINE_METHOD;
852+ }
801853 next ;
802854 }
803855
0 commit comments